diff --git a/.gitattributes b/.gitattributes
index fef51892bdc..cfeccf80957 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -82,6 +82,8 @@ src/Deck.java svneol=native#text/plain
src/DeckConverter.java svneol=native#text/plain
src/OldDeckIO.java svneol=native#text/plain
src/QuestData_State.java svneol=native#text/plain
+src/com/cloudgarden/layout/AnchorConstraint.java -text svneol=native#text/plain
+src/com/cloudgarden/layout/AnchorLayout.java -text svneol=native#text/plain
src/forge/Ability.java svneol=native#text/plain
src/forge/Ability_Activated.java svneol=native#text/plain
src/forge/Ability_Hand.java svneol=native#text/plain
@@ -140,6 +142,7 @@ src/forge/DownloadDeck.java -text svneol=native#text/plain
src/forge/EndOfTurn.java svneol=native#text/plain
src/forge/ExternalPanel.java svneol=native#text/plain
src/forge/FileUtil.java -text svneol=native#text/plain
+src/forge/GUI_Filter.java -text svneol=native#text/plain
src/forge/GameAction.java svneol=native#text/plain
src/forge/GameActionUtil.java svneol=native#text/plain
src/forge/GenerateConstructedDeck.java svneol=native#text/plain
diff --git a/res/cards.txt b/res/cards.txt
index 4dafccf888a..a43fdb86efa 100644
--- a/res/cards.txt
+++ b/res/cards.txt
@@ -1,3 +1,31 @@
+Archivist
+2 U U
+Creature Human Advisor
+no text
+1/1
+
+Fire Bowman
+R
+Creature Human Soldier Archer
+no text
+1/1
+
+Riding the Dilu Horse
+2 G
+Sorcery
+Target creature gets +2/+2 and gains horsemanship.
+
+Magus of the Coffers
+4 B
+Creature Human Wizard
+no text
+4/4
+
+Cabal Coffers
+no cost
+Land
+no text
+
Xiahou Dun, the One-Eyed
2 B B
Legendary Creature Human Soldier
diff --git a/res/main.properties b/res/main.properties
index 72112e17c7e..c56af6b006c 100644
--- a/res/main.properties
+++ b/res/main.properties
@@ -1,6 +1,6 @@
program/mail=mtgerror@yahoo.com
program/forum=http://www.slightlymagic.net/forum/viewforum.php?f=26
-program/version=MTG Forge -- official beta: 09/11/25, SVN revision: 101
+program/version=MTG Forge -- official beta: 09/11/25, SVN revision: 102
tokens--file=AllTokens.txt
diff --git a/src/com/cloudgarden/layout/AnchorConstraint.java b/src/com/cloudgarden/layout/AnchorConstraint.java
new file mode 100644
index 00000000000..6090dfaefd3
--- /dev/null
+++ b/src/com/cloudgarden/layout/AnchorConstraint.java
@@ -0,0 +1,80 @@
+/*
+ */
+package com.cloudgarden.layout;
+
+/**
+ * Used by both AnchorLayout (SWT) and AnchorLayoutManager (Swing)
+ */
+public class AnchorConstraint {
+
+ /**
+ * Meaning: This side is not anchored.
+ */
+ public static final int ANCHOR_NONE = 0;
+
+ /**
+ * (Relative anchor) Meaning: This side is anchored so that it always
+ * occurs a fixed fraction of
+ * the distance along it's parent's side. The position is calculated by
+ * the formula " position = (parent side)*(value)/1000 " so for
+ * instance if top=100 and topType == ANCHOR_REL then the
+ * value of y for this side would be (parent height)*top/1000.
+ */
+ public static final int ANCHOR_REL = 1;
+
+ /**
+ * (Absolute anchor) Meaning: This side is anchored a fixed distance
+ * in pixels (given by the value for this side) from it's parent's respective side.
+ * For instance, if bottomType == ANCHOR_ABS and bottom = 100 then the
+ * bottom side of this component will remain fixed 100 pixels from
+ * the bottom side of it's parent container.
+ */
+ public static final int ANCHOR_ABS = 2;
+
+ public int top;
+ public int bottom;
+ public int left;
+ public int right;
+ public int topType;
+ public int bottomType;
+ public int rightType;
+ public int leftType;
+
+ public AnchorConstraint() {
+ this(0, 0, 0, 0, ANCHOR_NONE, ANCHOR_NONE, ANCHOR_NONE, ANCHOR_NONE);
+ }
+
+ /**
+ * Creates an AnchorConstraint.
+ * @param top - value (relative or absolute) for top side
+ * @param right - like 'top' but for right side
+ * @param bottom - like 'top' but for bottom side
+ * @param left - like 'top' but for left side
+ * @param topType - either ANCHOR_ABS, ANCHOR_REL or ANCHOR_NONE
+ * to indicate whether the 'top' parameter is an absolute value (in pixels) or
+ * a fractional value (in 1/1000 ths) of the height of this component's parent,
+ * denoting where the anchor will be applied (if at all).
+ * @param rightType - like 'topType' but for right side
+ * @param bottomType - like 'topType' but for bottom side
+ * @param leftType - like 'topType' but for left side
+ */
+ public AnchorConstraint(
+ int top,
+ int right,
+ int bottom,
+ int left,
+ int topType,
+ int rightType,
+ int bottomType,
+ int leftType) {
+ this.top = top;
+ this.bottom = bottom;
+ this.left = left;
+ this.right = right;
+ this.topType = topType;
+ this.rightType = rightType;
+ this.bottomType = bottomType;
+ this.leftType = leftType;
+ }
+
+}
diff --git a/src/com/cloudgarden/layout/AnchorLayout.java b/src/com/cloudgarden/layout/AnchorLayout.java
new file mode 100644
index 00000000000..d8d20b7ddbe
--- /dev/null
+++ b/src/com/cloudgarden/layout/AnchorLayout.java
@@ -0,0 +1,263 @@
+/*
+ */
+package com.cloudgarden.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.LayoutManager2;
+import java.awt.Rectangle;
+import java.util.HashMap;
+
+/**
+ * Lays out components, using a combination of their "bounds" property
+ * and their AnchorConstraints layout constraint objects.
+ *
+ * Sides of the components can be anchored either absolutely (eg, if the
+ * right side is anchored absolutely then it will always be a fixed number
+ * of pixels from the right side of it's parent container) or relatively (ie,
+ * if any side is anchored relatively then it will always occur a fixed
+ * fraction of the way along it's parent's side). Or they can be not anchored,
+ * at all in which case they will occur at places determined by their
+ * component's "bounds" property and the anchoring of the component's
+ * other sides.
+ */
+public class AnchorLayout implements LayoutManager2 {
+
+ private int preferredWidth, preferredHeight, minHeight, minWidth;
+ private HashMap constraintMap = new HashMap();
+ private boolean sizesCalculated = false;
+ private Container container;
+
+ public AnchorLayout() {
+ super();
+ }
+
+ void initialize(Container parent) {
+ if (sizesCalculated)
+ return;
+ Component[] children = parent.getComponents();
+ preferredWidth = 10000;
+ preferredHeight = 10000;
+ minWidth = 0;
+ minHeight = 0;
+ Rectangle pb = parent.getBounds();
+ for (int i = 0; i < children.length; i++) {
+ Component child = children[i];
+ if (child != null) {
+ Object ld = constraintMap.get(child);
+ Rectangle b = child.getBounds();
+ Dimension pref = child.getPreferredSize();
+ Dimension min = child.getMaximumSize();
+ if (pref == null)
+ pref = child.getSize();
+ if (min == null)
+ min = child.getSize();
+ int minX = b.x + b.width;
+ int minY = b.y + b.height;
+ int maxX = b.x + b.width;
+ int maxY = b.y + b.height;
+ if (ld instanceof AnchorConstraint) {
+ AnchorConstraint ac = (AnchorConstraint) ld;
+ int acl = ac.left;
+ int acr = ac.right;
+ int aclt = ac.leftType;
+ int acrt = ac.rightType;
+
+ if (aclt == AnchorConstraint.ANCHOR_REL)
+ acl = acl * pb.width / 1000;
+ if (acrt == AnchorConstraint.ANCHOR_REL)
+ acr = pb.width - acr * pb.width / 1000;
+
+ if (aclt != AnchorConstraint.ANCHOR_NONE
+ && acrt != AnchorConstraint.ANCHOR_NONE)
+ maxX = acl + pref.width + acr;
+ if (aclt == AnchorConstraint.ANCHOR_NONE)
+ acl = 0;
+ if (acrt == AnchorConstraint.ANCHOR_NONE)
+ acr = 0;
+ minX = acl + min.width + acr;
+
+ int act = ac.top;
+ int acb = ac.bottom;
+ int actt = ac.topType;
+ int acbt = ac.bottomType;
+ if (actt == AnchorConstraint.ANCHOR_REL)
+ act = act * pb.height / 1000;
+ if (acbt == AnchorConstraint.ANCHOR_REL)
+ acb = pb.height - acb * pb.height / 1000;
+
+ if (actt != AnchorConstraint.ANCHOR_NONE
+ && acbt != AnchorConstraint.ANCHOR_NONE)
+ maxY = act + pref.height + acb;
+ if (actt == AnchorConstraint.ANCHOR_NONE)
+ act = 0;
+ if (acbt == AnchorConstraint.ANCHOR_NONE)
+ acb = 0;
+ minY = act + min.height + acb;
+ }
+ if (minX > minWidth)
+ minWidth = minX;
+ if (maxX > minWidth)
+ preferredWidth = maxX;
+ if (minY > minHeight)
+ minHeight = minY;
+ if (maxY > preferredHeight)
+ preferredHeight = maxY;
+ }
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
+ */
+ public void layoutContainer(Container container) {
+ this.setContainer(container);
+ Component children[] = container.getComponents();
+ Rectangle rect = container.getBounds();
+ int width = rect.width;
+ int height = rect.height;
+ for (int i = 0; i < children.length; i++) {
+ Component child = children[i];
+ if (child != null) {
+ Object ld = constraintMap.get(child);
+ Rectangle b = child.getBounds();
+ Dimension pref = child.getPreferredSize();
+ if (pref == null)
+ pref = child.getSize();
+ if (ld instanceof AnchorConstraint) {
+ AnchorConstraint ac = (AnchorConstraint) ld;
+ int acl = ac.left;
+ int acr = ac.right;
+ int aclt = ac.leftType;
+ int acrt = ac.rightType;
+ if (aclt == AnchorConstraint.ANCHOR_REL)
+ acl = acl * width / 1000;
+ if (acrt == AnchorConstraint.ANCHOR_REL)
+ acr = width - acr * width / 1000;
+
+ if (aclt != AnchorConstraint.ANCHOR_NONE) {
+ if (acrt != AnchorConstraint.ANCHOR_NONE) {
+ b.width = width - acr - acl;
+ b.x = acl;
+ } else {
+ b.width = pref.width;
+ if (b.width + acl > width)
+ b.width = width - acl;
+ b.x = acl;
+ }
+ } else {
+ if (acrt != AnchorConstraint.ANCHOR_NONE) {
+ b.x = width - acr - pref.width;
+ }
+ b.width = pref.width;
+ if (b.width + b.x > width)
+ b.width = width - b.x;
+ }
+
+ int act = ac.top;
+ int acb = ac.bottom;
+ int actt = ac.topType;
+ int acbt = ac.bottomType;
+ if (actt == AnchorConstraint.ANCHOR_REL)
+ act = act * height / 1000;
+ if (acbt == AnchorConstraint.ANCHOR_REL)
+ acb = height - acb * height / 1000;
+
+ if (actt != AnchorConstraint.ANCHOR_NONE) {
+ if (acbt != AnchorConstraint.ANCHOR_NONE) {
+ b.height = height - acb - act;
+ b.y = act;
+ } else {
+ b.height = pref.height;
+ if (b.height + act > height)
+ b.height = height - act;
+ b.y = act;
+ }
+ } else {
+ if (acbt != AnchorConstraint.ANCHOR_NONE) {
+ b.y = height - acb - pref.height;
+ }
+ b.height = pref.height;
+ if (b.height + b.y > height)
+ b.height = height - b.y;
+ }
+ child.setBounds(b);
+ }
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
+ */
+ public void addLayoutComponent(String name, Component comp) {}
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
+ */
+ public void removeLayoutComponent(Component comp) {
+ constraintMap.remove(comp);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
+ */
+ public Dimension preferredLayoutSize(Container parent) {
+ initialize(parent);
+ return new Dimension(preferredWidth, preferredHeight);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
+ */
+ public Dimension minimumLayoutSize(Container parent) {
+ initialize(parent);
+ return new Dimension(minWidth, minHeight);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager2#addLayoutComponent(java.awt.Component, java.lang.Object)
+ */
+ public void addLayoutComponent(Component comp, Object constraints) {
+ constraintMap.put(comp, constraints);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container)
+ */
+ public Dimension maximumLayoutSize(Container target) {
+ return preferredLayoutSize(target);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container)
+ */
+ public float getLayoutAlignmentX(Container target) {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container)
+ */
+ public float getLayoutAlignmentY(Container target) {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container)
+ */
+ public void invalidateLayout(Container target) {
+ sizesCalculated = false;
+ }
+
+ public void setContainer(Container container) {
+ this.container = container;
+ }
+
+ public Container getContainer() {
+ return container;
+ }
+
+}
diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java
index 996dd8ab69e..00daedc6860 100644
--- a/src/forge/CardFactory.java
+++ b/src/forge/CardFactory.java
@@ -17067,9 +17067,6 @@ return land.size() > 1 && CardFactoryUtil.AI_isMainPhase();
{
final Spell spell = new Spell(card)
{
- /**
- *
- */
private static final long serialVersionUID = 2626237206744317044L;
public void resolve()
@@ -17144,6 +17141,53 @@ return land.size() > 1 && CardFactoryUtil.AI_isMainPhase();
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
+
+ //*************** START *********** START **************************
+ else if(cardName.equals("Riding the Dilu Horse"))
+ {
+ SpellAbility spell = new Spell(card)
+ {
+ private static final long serialVersionUID = -620930445462994580L;
+
+ public boolean canPlayAI()
+ {
+ PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
+
+ CardList list = new CardList(play.getCards());
+ list = list.filter(new CardListFilter()
+ {
+ public boolean addCard(Card c)
+ {
+ return c.isCreature() && !c.getKeyword().contains("Horsemanship") && !c.getKeyword().contains("Defender");
+ }
+ });
+
+ Card c = CardFactoryUtil.AI_getBestCreature(list, card);
+ setTargetCard(c);
+ return list.size() > 0;
+ }
+
+ public void resolve()
+ {
+ final Card[] target = new Card[1];
+
+
+ target[0] = getTargetCard();
+ if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]))
+ {
+ target[0].addTempAttackBoost(2);
+ target[0].addTempDefenseBoost(2);
+ target[0].addExtrinsicKeyword("Horsemanship");
+
+ //String s = target[0].getText();
+ target[0].setText("(+2/+2 and Horsemanship from " +card+")");
+ }
+ }//resolve()
+ };
+ spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
+ card.clearSpellAbility();
+ card.addSpellAbility(spell);
+ }//*************** END ************ END **************************
// Cards with Cycling abilities
// -1 means keyword "Cycling" not found
diff --git a/src/forge/CardFactory_Creatures.java b/src/forge/CardFactory_Creatures.java
index 6d04cfc44cf..a883926ba02 100644
--- a/src/forge/CardFactory_Creatures.java
+++ b/src/forge/CardFactory_Creatures.java
@@ -17068,6 +17068,119 @@ public class CardFactory_Creatures {
card.addSpellAbility(ability);
}//*************** END ************ END **************************
+ //*************** START *********** START **************************
+ if (cardName.equals("Magus of the Coffers"))
+ {
+ final SpellAbility ability = new Ability_Tap(card, "2")
+ {
+
+ private static final long serialVersionUID = 138661285416402582L;
+ public void resolve()
+ {
+ Card mp = AllZone.ManaPool;//list.getCard(0);
+
+ CardList swamps = new CardList(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards());
+ swamps = swamps.getType("Swamp");
+
+ for(int i=0;i