Semi-Random Theme Deck Generator
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
31 posts
• Page 2 of 3 • 1, 2, 3
Re: Semi-Random Theme Deck Generator
by Sloth » 24 Sep 2010, 09:58
Those are some nice themes Marek14. I'm sure we will find a way to implement them, however the "Adventure mode" turns out.
I guess the hardest part will be to balance them and/or give them a difficulty level or something.
I guess the hardest part will be to balance them and/or give them a difficulty level or something.
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Semi-Random Theme Deck Generator
by Marek14 » 24 Sep 2010, 11:03
Thanks 
I'm sure some more themes could be found, but for starters I focused on the idea that these are decks played by creatures (and planeswalkers).

I'm sure some more themes could be found, but for starters I focused on the idea that these are decks played by creatures (and planeswalkers).
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 24 Sep 2010, 11:27
I don't think we need to limit this concept to just the creature battles. This can be a fun tool for the regular constructed games, both for the AI and human.
Has anyone figured out why my change to remove the remove list is causing the slow down? The fan in my laptop died, so I haven't had a chance to really look into it.
Has anyone figured out why my change to remove the remove list is causing the slow down? The fan in my laptop died, so I haven't had a chance to really look into it.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by Sloth » 24 Sep 2010, 13:25
I found it: You deleted a "!" before c.getSVar("RemAIDeck").equals("True"), so decks were generated only from cards that have RemAIDeck:True. Since their number is so small and the Generation is trial and error it took so long. Fixed with one character: "!".Rob Cashwalker wrote:Has anyone figured out why my change to remove the remove list is causing the slow down? The fan in my laptop died, so I haven't had a chance to really look into it.

-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 24 Sep 2010, 13:36
woo-hoo! Thanks for the catch. I'm glad it was that sort of simple mistake and not something ancillary to the theme deck stuff.
In other news my boss is bringing in his twin of my laptop so I can swap fans.... (his has a cracked LCD)
Sometime this evening I'll start to rework this generator with some of the concepts above.
In other news my boss is bringing in his twin of my laptop so I can swap fans.... (his has a cracked LCD)
Sometime this evening I'll start to rework this generator with some of the concepts above.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 26 Sep 2010, 03:28
OK, based on the discussions so far, I've revised the format.
It now expects the following:
[Group MaxCnt=# Percentage=#]
Cards
Cards
[/Group]
and somewhat optional:
BasicLandPercentage=#
(if not defined then all remaining card slots not filled will be basic lands)
Basic Lands are added in proportion to the colors represented by the cards selected.
If after the deck is essentially assembled, if it is over or under the specified Size, then random cards (no more than 4x) already selected in the deck will be added or removed to make up the difference. (Basic Lands will never be removed to meet the Size)
Yes the debug window listing the deck contents is still here for your testing pleasure. I'm thinking of making it an option of the theme file, add a line "Testing" and the debug window pops up.
It now expects the following:
[Group MaxCnt=# Percentage=#]
Cards
Cards
[/Group]
and somewhat optional:
BasicLandPercentage=#
(if not defined then all remaining card slots not filled will be basic lands)
Basic Lands are added in proportion to the colors represented by the cards selected.
If after the deck is essentially assembled, if it is over or under the specified Size, then random cards (no more than 4x) already selected in the deck will be added or removed to make up the difference. (Basic Lands will never be removed to meet the Size)
Yes the debug window listing the deck contents is still here for your testing pleasure. I'm thinking of making it an option of the theme file, add a line "Testing" and the debug window pops up.
- Code: Select all
package forge;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import forge.error.ErrorViewer;
public class GenerateThemeDeck
{
private BufferedReader in = null;
public GenerateThemeDeck()
{
}
public ArrayList<String> getThemeNames()
{
ArrayList<String> ltNames = new ArrayList<String>();
File file = new File("res/quest/themes/");
if(!file.exists())
throw new RuntimeException("GenerateThemeDeck : getThemeNames error -- file not found -- filename is "
+ file.getAbsolutePath());
if (!file.isDirectory())
throw new RuntimeException("GenerateThemeDeck : getThemeNames error -- not a direcotry -- "
+ file.getAbsolutePath());
String[] fileList = file.list();
for (int i=0; i<fileList.length; i++)
{
if (fileList[i].endsWith(".thm"))
ltNames.add(fileList[i].substring(0, fileList[i].indexOf(".thm")));
}
return ltNames;
}
public CardList getThemeDeck(String ThemeName, int Size)
{
CardList tDeck = new CardList();
ArrayList<Grp> Groups = new ArrayList<Grp>();
Map<String,Integer> CardCounts = new HashMap<String,Integer>();
String s = "";
int BLandPercentage = 0;
// read theme file
String tFileName = "res/quest/themes/" + ThemeName + ".thm";
File tFile = new File(tFileName);
if(!tFile.exists())
throw new RuntimeException("GenerateThemeDeck : getThemeDeck -- file not found -- filename is " + tFile.getAbsolutePath());
try {
in = new BufferedReader(new FileReader(tFile));
} catch(Exception ex) {
ErrorViewer.showError(ex, "File \"%s\" exception", tFile.getAbsolutePath());
throw new RuntimeException("GenerateThemeDeck : getThemeDeck -- file exception -- filename is " + tFile.getPath());
}
s = readLine();
while (!s.equals("End"))
{
if (s.startsWith("[Group"))
{
Grp G = new Grp();
String ss[] = s.replaceAll("[\\[\\]]", "").split(" ");
for (int i=0; i<ss.length; i++)
{
if (ss[i].startsWith("Percentage"))
{
String p = ss[i].substring("Percentage".length() + 1);
G.Percentage = Integer.parseInt(p);
}
if (ss[i].startsWith("MaxCnt"))
{
String m = ss[i].substring("MaxCnt".length() + 1);
G.MaxCnt = Integer.parseInt(m);
}
}
s = readLine();
while (!s.equals("[/Group]"))
{
G.Cardnames.add(s);
CardCounts.put(s, 0);
s = readLine();
}
Groups.add(G);
}
if (s.equals("BasicLandPercentage"))
BLandPercentage = Integer.parseInt(s.substring("BasicLandPercentage".length() + 1));
s = readLine();
}
try {
in.close();
} catch (IOException ex) {
ErrorViewer.showError(ex, "File \"%s\" exception", tFile.getAbsolutePath());
throw new RuntimeException("GenerateThemeDeck : getThemeDeck -- file exception -- filename is " + tFile.getPath());
}
String tmpDeck = "";
// begin assigning cards to the deck
Random r = new Random();
for (int i=0; i<Groups.size(); i++)
{
Grp G = Groups.get(i);
float p = (float) ((float)G.Percentage * .01);
int GrpCnt = (int)(p * (float)Size);
int cnSize = G.Cardnames.size();
tmpDeck += "Group" + i + ":" + GrpCnt + "\n";
for (int j=0; j<GrpCnt; j++)
{
s = G.Cardnames.get(r.nextInt(cnSize));
int lc = 0;
while (CardCounts.get(s) >= G.MaxCnt || lc > Size) // don't keep looping forever
{
s = G.Cardnames.get(r.nextInt(cnSize));
lc++;
}
if (lc > Size)
throw new RuntimeException("GenerateThemeDeck : getThemeDeck -- looped too much -- filename is " + tFile.getAbsolutePath());
int n = CardCounts.get(s);
tDeck.add(AllZone.CardFactory.getCard(s, Constant.Player.Computer));
CardCounts.put(s, n + 1);
tmpDeck += s + "\n";
}
}
int numBLands = 0;
if (BLandPercentage > 0) // if theme explicitly defines this
{
float p = (float)((float)BLandPercentage * .01);
numBLands = (int)(p * (float)Size);
}
else // otherwise, just fill in the rest of the deck with basic lands
numBLands = Size - tDeck.size();
tmpDeck += "numBLands:" + numBLands + "\n";
if (numBLands > 0) // attempt to optimize basic land counts according to color representation
{
CCnt ClrCnts[] = {new CCnt("Plains", 0),
new CCnt("Island", 0),
new CCnt("Swamp", 0),
new CCnt("Mountain", 0),
new CCnt("Forest", 0)};
// count each instance of a color in mana costs
// TODO: count hybrid mana differently?
// TODO: count all color letters? ie: 2 W W counts as 2
for (int i=0;i<tDeck.size(); i++)
{
Card c = tDeck.get(i);
String mc = c.getManaCost();
if (mc.contains("W"))
ClrCnts[0].Count++;
if (mc.contains("U"))
ClrCnts[1].Count++;
if (mc.contains("B"))
ClrCnts[2].Count++;
if (mc.contains("R"))
ClrCnts[3].Count++;
if (mc.contains("G"))
ClrCnts[4].Count++;
}
int totalColor = 0;
for (int i=0;i<5; i++)
{
totalColor += ClrCnts[i].Count;
tmpDeck += ClrCnts[i].Color + ":" + ClrCnts[i].Count + "\n";
}
tmpDeck += "totalColor:" + totalColor + "\n";
for (int i=0; i<5; i++)
{
if (ClrCnts[i].Count > 0)
{ // calculate number of lands for each color
float p = (float)ClrCnts[i].Count / (float)totalColor;
int nLand = (int)((float)numBLands * p);
tmpDeck += "numLand-" + ClrCnts[i].Color + ":" + nLand + "\n";
for (int j=0; j<nLand; j++)
tDeck.add(AllZone.CardFactory.getCard(ClrCnts[i].Color, Constant.Player.Computer));
}
}
}
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
if (tDeck.size() < Size)
{
int diff = Size - tDeck.size();
for (int i=0; i<diff; i++)
{
s = tDeck.get(r.nextInt(tDeck.size())).getName();
while (CardCounts.get(s) >= 4)
s = tDeck.get(r.nextInt(tDeck.size())).getName();
int n = CardCounts.get(s);
tDeck.add(AllZone.CardFactory.getCard(s, Constant.Player.Computer));
CardCounts.put(s, n + 1);
tmpDeck += "Added:" + s + "\n";
}
}
else if (tDeck.size() > Size)
{
int diff = tDeck.size() - Size;
for (int i=0; i<diff; i++)
{
Card c = tDeck.get(r.nextInt(tDeck.size()));
while (c.getType().contains("Basic"))
c = tDeck.get(r.nextInt(tDeck.size()));
tDeck.remove(c);
tmpDeck += "Removed:" + s + "\n";
}
}
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
ErrorViewer.showError(tmpDeck);
return tDeck;
}
private String readLine() {
//makes the checked exception, into an unchecked runtime exception
try {
String s = in.readLine();
if(s != null) s = s.trim();
return s;
} catch(Exception ex) {
ErrorViewer.showError(ex);
throw new RuntimeException("GenerateThemeDeck : readLine error");
}
}//readLine(Card)
}
class CCnt
{
public String Color;
public int Count;
public CCnt(String clr, int cnt)
{
Color = clr;
Count = cnt;
}
}
class Grp
{
public ArrayList<String> Cardnames = new ArrayList<String>();
public int MaxCnt;
public int Percentage;
}
- Code: Select all
BasicLandPercentage=34
[Group MaxCnt=3 Percentage=10]
Blasted Landscape
Darksteel Citadel
Drifting Meadow
[/Group]
[Group MaxCnt=4 Percentage=30]
Glorious Anthem
Isamaru, Hound of Konda
Savannah Lions
Silvercoat Lion
Skyhunter Prowler
Stand Firm
Sunlance
[/Group]
[Group MaxCnt=3 Percentage=25]
Standing Troops
Staunch Defenders
Steadfast Guard
Steadfastness
Steppe Lynx
Swords to Plowshares
Unmake
Valorous Charge
[/Group]
End
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by Sloth » 26 Sep 2010, 08:31
Thank you Rob, this should be everything I need to design some fine themes. I think I will toy around with it a bit today.
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 27 Sep 2010, 00:15
I see you added the domain theme. However it isn't correct. The MaxCnt parameter is the max number of any one card. In other words, no more than 4. This is intended to give a card group more diversity. The actual card count of the entire group is purely based on the percentage.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by mtgrares » 28 Sep 2010, 17:19
I really like the idea of a Semi-Random Theme Deck Generator. I'm not much of a deck builder and I enjoy playing against the AI with the Generate Deck option. It is hard to balance "how random should it be" because some randomness is good but too much randomness is chaotic. Balancing the converted mana cost is also good because it will make the decks more playable. (Sometimes the generated decks is too random and unplayable.)
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 28 Sep 2010, 19:13
I'm working on a new true random deck generator, based on some of the ideas I had with the theme generator. One of our feature requests are random decks with user-chosen colors, so that's what I'm doing.
The trick I'm trying to implement is avoiding singleton decks, by pre-selecting a small pool of cards, then selecting the actual deck from it.
The trick I'm trying to implement is avoiding singleton decks, by pre-selecting a small pool of cards, then selecting the actual deck from it.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 30 Sep 2010, 11:52
I just submitted an update to the theme deck generator. If the theme file contains a line "Testing" then it will display the deck list in an ErrorViewer window, otherwise, it will just play the deck.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by Sloth » 13 Oct 2010, 19:54
I just added 3 new themes, but sometimes the theme deck generator returns a null exception. (I checked that all cards are present). I used odd numbers for the percentages, though.Rob Cashwalker wrote:I just submitted an update to the theme deck generator. If the theme file contains a line "Testing" then it will display the deck list in an ErrorViewer window, otherwise, it will just play the deck.
Example:
- BasicLandPercentage=20
[Group MaxCnt=4 Percentage=19]
Scrubland
Arcane Sanctum
Darksteel Citadel
[/Group]
[Group MaxCnt=4 Percentage=33]
Darksteel Ingot
Darksteel Gargoyle
Stuffy Doll
Phylactery Lich
Darksteel Axe
Darksteel Myr
Darksteel Sentinel
[/Group]
[Group MaxCnt=1 Percentage=5]
Myr Matrix
Darksteel Colossus
Darksteel Juggernaut
Sapling of Colfenor
Ulamog, the Infinite Gyre
Konda, Lord of Eiganjo
[/Group]
[Group MaxCnt=4 Percentage=23]
Wrath of God
Damnation
Day of Judgment
Planar Cleansing
Akroma's Vengeance
Winds of Rath
[/Group]
End
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Semi-Random Theme Deck Generator
by Rob Cashwalker » 13 Oct 2010, 20:27
error trace for the nulls?
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Semi-Random Theme Deck Generator
by Sloth » 13 Oct 2010, 20:40
Rob Cashwalker wrote:error trace for the nulls?
- Code: Select all
Detailed error trace:
java.lang.NullPointerException
at forge.GenerateThemeDeck.getThemeDeck(Unknown Source)
at forge.Gui_NewGame.generateConstructedThemeDeck(Unknown Source)
at forge.Gui_NewGame.genDecks(Unknown Source)
at forge.Gui_NewGame.startButton_actionPerformed(Unknown Source)
at forge.Gui_NewGame$11.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Semi-Random Theme Deck Generator
by friarsol » 13 Oct 2010, 21:10
I think I was getting them in the same place. It looks like the Basic Lands are rounding down when there are more than one to fill in. For the deck I was building it was trying to add 15 basic lands. But after calculation it was only adding 8 forests and 6 plains for a total of 14.
Somewhere there needs to be an extra check to see if the amount of Basics generated was the same as expected and if not do something about it.
Line for me was: at forge.GenerateThemeDeck.getThemeDeck(GenerateThemeDeck.java:238)
Somewhere there needs to be an extra check to see if the amount of Basics generated was the same as expected and if not do something about it.
Line for me was: at forge.GenerateThemeDeck.getThemeDeck(GenerateThemeDeck.java:238)
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
31 posts
• Page 2 of 3 • 1, 2, 3
Who is online
Users browsing this forum: TRT and 47 guests