diff --git a/.gitattributes b/.gitattributes index 9aaf531bf98..8d35f438274 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13553,8 +13553,8 @@ src/main/java/forge/Singletons.java svneol=native#text/plain src/main/java/forge/StaticEffect.java svneol=native#text/plain src/main/java/forge/StaticEffects.java svneol=native#text/plain src/main/java/forge/card/AggregationMethod.java -text -src/main/java/forge/card/BoosterData.java -text src/main/java/forge/card/BoosterGenerator.java svneol=native#text/plain +src/main/java/forge/card/BoosterTemplate.java -text src/main/java/forge/card/CardAiHints.java -text src/main/java/forge/card/CardBlock.java -text src/main/java/forge/card/CardCharacteristics.java -text @@ -13572,7 +13572,7 @@ src/main/java/forge/card/CardType.java -text src/main/java/forge/card/ColorSet.java -text src/main/java/forge/card/DeckHints.java -text src/main/java/forge/card/EditionCollection.java svneol=native#text/plain -src/main/java/forge/card/FatPackData.java -text +src/main/java/forge/card/FatPackTemplate.java -text src/main/java/forge/card/FormatCollection.java -text src/main/java/forge/card/ICardCharacteristics.java -text src/main/java/forge/card/ICardFace.java -text @@ -14306,6 +14306,7 @@ src/main/java/forge/item/ItemPoolView.java -text src/main/java/forge/item/ItemPredicate.java -text src/main/java/forge/item/OpenablePack.java -text src/main/java/forge/item/PreconDeck.java -text +src/main/java/forge/item/PrintSheet.java -text src/main/java/forge/item/TournamentPack.java -text src/main/java/forge/item/package-info.java -text src/main/java/forge/model/BuildInfo.java -text diff --git a/res/blockdata/boosters.txt b/res/blockdata/boosters.txt index 70623dcb8af..4fa1a1e521e 100644 --- a/res/blockdata/boosters.txt +++ b/res/blockdata/boosters.txt @@ -1,79 +1,80 @@ -Set:10E|LandSet:10E|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:2ED|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:3ED|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:4ED|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:5DN|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:5ED|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:6ED|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:7ED|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:8ED|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:9ED|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:ALA|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:ALL|Commons:8|Uncommons:3|Rares:1|Images:1 -Set:APC|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:ARB|LandSet:ALA|Commons:10|Uncommons:3|Rares:1|Images:3 -Set:ARN|Commons:6|Uncommons:2|Images:1 -Set:ATQ|Commons:5|Uncommons:2|Rares:1|Images:1 -Set:AVR|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:BOK|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:CFX|LandSet:ALA|Commons:10|Uncommons:3|Rares:1|Images:3 -Set:CHK|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:CHR|Commons:9|Uncommons:3|Images:1 -Set:CSP|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:DIS|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:DKA|LandSet:ISD|Commons:9|Uncommons:3|DoubleFaced:1|Rares:1|Images:3 -Set:DRK|Commons:6|Rares:2|Images:1 -Set:DST|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:EVE|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:EXO|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:FEM|Commons:5|Uncommons:2|Rares:1|Images:1 -Set:FUT|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:GPT|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:GTC|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:HML|Commons:6|Uncommons:2|Images:1 -Set:ICE|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:INV|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:ISD|Commons:9|Uncommons:3|DoubleFaced:1|Rares:1|Images:5 -Set:JUD|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:LEA|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:LEB|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:LEG|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:LGN|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:LRW|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:M10|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:M11|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:M12|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:M13|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:MBS|Commons:10|Uncommons:3|Rares:1|Images:3 -Set:MIR|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:MMQ|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:MOR|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:MRD|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:NMS|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:NPH|Commons:10|Uncommons:3|Rares:1|Images:3 -Set:ODY|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:ONS|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:PCY|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:PLC|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:PLS|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:PO2|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:POR|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:PTK|Commons:5|Uncommons:2|Rares:1|Images:1 -Set:RAV|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:ROE|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:RTR|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:SCG|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:SHM|Commons:11|Uncommons:3|Rares:1|Images:5 -Set:SOK|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:SOM|Commons:10|Uncommons:3|Rares:1|Images:5 -Set:STH|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:TMP|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:TOR|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:TSP|Commons:10|Uncommons:3|Rares:1|Special:1|Images:5 -Set:UDS|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:ULG|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:USG|Commons:11|Uncommons:3|Rares:1|Images:3 -Set:VIS|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:WTH|Commons:11|Uncommons:3|Rares:1|Images:1 -Set:WWK|LandSet:ZEN|Commons:10|Uncommons:3|Rares:1|Images:3 -Set:ZEN|Commons:10|Uncommons:3|Rares:1|Images:5 +10E: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +2ED: 1 covers, 11 Common, 3 Uncommon, 1 Rare +3ED: 1 covers, 11 Common, 3 Uncommon, 1 Rare +4ED: 5 covers, 11 Common, 3 Uncommon, 1 Rare +5DN: 3 covers, 11 Common, 3 Uncommon, 1 Rare +5ED: 5 covers, 11 Common, 3 Uncommon, 1 Rare +6ED: 1 covers, 11 Common, 3 Uncommon, 1 Rare +7ED: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +8ED: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +9ED: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +ALA: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +ALL: 1 covers, 8 Common, 3 Uncommon, 1 Rare +APC: 1 covers, 11 Common, 3 Uncommon, 1 Rare +ARB: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand ALA +ARN: 1 covers, 6 Common, 2 UncommonRare +ATQ: 1 covers, 6 Common, 2 UncommonRare +AVR: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +BOK: 3 covers, 11 Common, 3 Uncommon, 1 Rare +CFX: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand ALA +CHK: 5 covers, 11 Common, 3 Uncommon, 1 Rare +CHR: 1 covers, 9 Common, 3 UncommonRare +CSP: 3 covers, 11 Common, 3 Uncommon, 1 Rare +DGM: 3 covers, 10 Common, 3 Uncommon, 1 Rare:!name("Maze's End"), 1 MazeLand +DIS: 3 covers, 11 Common, 3 Uncommon, 1 Rare +DKA: 3 covers, 9 Common:!dfc, 3 Uncommon:!dfc, 1 Rare:!dfc, 1 Any:dfc, 1 BasicLand ISD +DRK: 1 covers, 6 Common, 2 UncommonRare +DST: 3 covers, 11 Common, 3 Uncommon, 1 Rare +EVE: 3 covers, 11 Common, 3 Uncommon, 1 Rare +EXO: 1 covers, 11 Common, 3 Uncommon, 1 Rare +FEM: 1 covers, 5 Common, 2 Uncommon, 1 Rare +FUT: 3 covers, 11 Common, 3 Uncommon, 1 Rare +GPT: 3 covers, 11 Common, 3 Uncommon, 1 Rare +GTC: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +HML: 1 covers, 6 Common, 2 UncommonRare +ICE: 5 covers, 11 Common, 3 Uncommon, 1 Rare +INV: 3 covers, 11 Common, 3 Uncommon, 1 Rare +ISD: 5 covers, 9 Common:!dfc, 3 Uncommon:!dfc, 1 Rare:!dfc, 1 Any:dfc, 1 BasicLand +JUD: 1 covers, 11 Common, 3 Uncommon, 1 Rare +LEA: 1 covers, 11 Common, 3 Uncommon, 1 Rare +LEB: 1 covers, 11 Common, 3 Uncommon, 1 Rare +LEG: 1 covers, 11 Common, 3 Uncommon, 1 Rare +LGN: 3 covers, 11 Common, 3 Uncommon, 1 Rare +LRW: 5 covers, 11 Common, 3 Uncommon, 1 Rare +M10: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +M11: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +M12: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +M13: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +MBS: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +MIR: 5 covers, 11 Common, 3 Uncommon, 1 Rare +MMQ: 3 covers, 11 Common, 3 Uncommon, 1 Rare +MOR: 3 covers, 11 Common, 3 Uncommon, 1 Rare +MRD: 5 covers, 11 Common, 3 Uncommon, 1 Rare +NMS: 1 covers, 11 Common, 3 Uncommon, 1 Rare +NPH: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +ODY: 3 covers, 11 Common, 3 Uncommon, 1 Rare +ONS: 5 covers, 11 Common, 3 Uncommon, 1 Rare +PCY: 1 covers, 11 Common, 3 Uncommon, 1 Rare +PLC: 3 covers, 11 Common, 3 Uncommon, 1 Rare +PLS: 1 covers, 11 Common, 3 Uncommon, 1 Rare +PO2: 1 covers, 11 Common, 3 Uncommon, 1 Rare +POR: 5 covers, 11 Common, 3 Uncommon, 1 Rare +PTK: 1 covers, 5 Common, 2 Uncommon, 1 Rare, 2 BasicLand +RAV: 5 covers, 11 Common, 3 Uncommon, 1 Rare +ROE: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +RTR: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +SCG: 3 covers, 11 Common, 3 Uncommon, 1 Rare +SHM: 5 covers, 11 Common, 3 Uncommon, 1 Rare +SOK: 3 covers, 11 Common, 3 Uncommon, 1 Rare +SOM: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand +STH: 1 covers, 11 Common, 3 Uncommon, 1 Rare +TMP: 3 covers, 11 Common, 3 Uncommon, 1 Rare +TOR: 1 covers, 11 Common, 3 Uncommon, 1 Rare +TSP: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 TimeShifted +UDS: 1 covers, 11 Common, 3 Uncommon, 1 Rare +ULG: 1 covers, 11 Common, 3 Uncommon, 1 Rare +USG: 3 covers, 11 Common, 3 Uncommon, 1 Rare +VIS: 1 covers, 11 Common, 3 Uncommon, 1 Rare +WTH: 1 covers, 11 Common, 3 Uncommon, 1 Rare +WWK: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand ZEN +ZEN: 5 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand \ No newline at end of file diff --git a/res/blockdata/fatpacks.txt b/res/blockdata/fatpacks.txt index e8d69f35247..9589c82555b 100644 --- a/res/blockdata/fatpacks.txt +++ b/res/blockdata/fatpacks.txt @@ -1,49 +1,50 @@ -Set:MMQ|LandSet:MMQ|Boosters:6|BasicLands:30 -Set:NMS|LandSet:MMQ|Boosters:6|BasicLands:0 -Set:PCY|LandSet:MMQ|Boosters:6|BasicLands:0 -Set:INV|LandSet:INV|Boosters:6|BasicLands:0 -Set:PLS|LandSet:INV|Boosters:6|BasicLands:0 -Set:APC|LandSet:INV|Boosters:6|BasicLands:0 -Set:ODY|LandSet:ODY|Boosters:6|BasicLands:0 -Set:TOR|LandSet:ODY|Boosters:6|BasicLands:0 -Set:JUD|LandSet:ODY|Boosters:6|BasicLands:0 -Set:ONS|LandSet:ONS|Boosters:9|BasicLands:30 -Set:LGN|LandSet:ONS|Boosters:6|BasicLands:0 -Set:SCG|LandSet:ONS|Boosters:6|BasicLands:0 -Set:MRD|LandSet:MRD|Boosters:6|BasicLands:0 -Set:DST|LandSet:MRD|Boosters:6|BasicLands:0 -Set:5DN|LandSet:MRD|Boosters:6|BasicLands:0 -Set:CHK|LandSet:CHK|Boosters:6|BasicLands:0 -Set:BOK|LandSet:CHK|Boosters:6|BasicLands:0 -Set:SOK|LandSet:CHK|Boosters:6|BasicLands:0 -Set:9ED|LandSet:9ED|Boosters:6|BasicLands:40 -Set:RAV|LandSet:RAV|Boosters:6|BasicLands:40 -Set:GPT|LandSet:RAV|Boosters:6|BasicLands:40 -Set:DIS|LandSet:RAV|Boosters:6|BasicLands:40 -Set:CSP|LandSet:CSP|Boosters:6|BasicLands:40 -Set:TSP|LandSet:TSP|Boosters:6|BasicLands:40 -Set:PLC|LandSet:TSP|Boosters:6|BasicLands:40 -Set:FUT|LandSet:TSP|Boosters:6|BasicLands:40 -Set:10E|LandSet:10E|Boosters:6|BasicLands:40 -Set:LRW|LandSet:LRW|Boosters:6|BasicLands:40 -Set:MOR|LandSet:LRW|Boosters:6|BasicLands:40 -Set:SHM|LandSet:SHM|Boosters:8|BasicLands:40 -Set:EVE|LandSet:SHM|Boosters:8|BasicLands:40 -Set:ALA|LandSet:ALA|Boosters:8|BasicLands:40 -Set:CFX|LandSet:ALA|Boosters:8|BasicLands:40 -Set:ARB|LandSet:ALA|Boosters:8|BasicLands:40 -Set:M10|LandSet:M10|Boosters:8|BasicLands:40 -Set:ZEN|LandSet:ZEN|Boosters:8|BasicLands:40 -Set:WWK|LandSet:ZEN|Boosters:8|BasicLands:40 -Set:ROE|LandSet:ROE|Boosters:8|BasicLands:40 -Set:M11|LandSet:M11|Boosters:8|BasicLands:40 -Set:SOM|LandSet:SOM|Boosters:8|BasicLands:40 -Set:MBS|LandSet:MBS|Boosters:9|BasicLands:80 -Set:NPH|LandSet:NPH|Boosters:9|BasicLands:80 -Set:M12|LandSet:M12|Boosters:9|BasicLands:80 -Set:ISD|LandSet:ISD|Boosters:9|BasicLands:70 -Set:DKA|LandSet:ISD|Boosters:9|BasicLands:70 -Set:AVR|LandSet:AVR|Boosters:9|BasicLands:80 -Set:M13|LandSet:M13|Boosters:9|BasicLands:80 -Set:RTR|LandSet:RTR|Boosters:9|BasicLands:80 -Set:GTC|LandSet:RTR|Boosters:9|BasicLands:80 +MMQ: 6 Boosters, 30 BasicLands +NMS: 6 Boosters +PCY: 6 Boosters +INV: 6 Boosters +PLS: 6 Boosters +APC: 6 Boosters +ODY: 6 Boosters +TOR: 6 Boosters +JUD: 6 Boosters +ONS: 9 Boosters, 30 BasicLands +LGN: 6 Boosters +SCG: 6 Boosters +MRD: 6 Boosters +DST: 6 Boosters +5DN: 6 Boosters +CHK: 6 Boosters +BOK: 6 Boosters +SOK: 6 Boosters +9ED: 6 Boosters, 40 BasicLands +RAV: 6 Boosters, 40 BasicLands +GPT: 6 Boosters, 40 BasicLands RAV +DIS: 6 Boosters, 40 BasicLands RAV +CSP: 6 Boosters, 40 BasicLands +TSP: 6 Boosters, 40 BasicLands +PLC: 6 Boosters, 40 BasicLands TSP +FUT: 6 Boosters, 40 BasicLands TSP +10E: 6 Boosters, 40 BasicLands +LRW: 6 Boosters, 40 BasicLands +MOR: 6 Boosters, 40 BasicLands LRW +SHM: 8 Boosters, 40 BasicLands +EVE: 8 Boosters, 40 BasicLands SHM +ALA: 8 Boosters, 40 BasicLands +CFX: 8 Boosters, 40 BasicLands ALA +ARB: 8 Boosters, 40 BasicLands ALA +M10: 8 Boosters, 40 BasicLands +ZEN: 8 Boosters, 40 BasicLands +WWK: 8 Boosters, 40 BasicLands ZEN +ROE: 8 Boosters, 40 BasicLands +M11: 8 Boosters, 40 BasicLands +SOM: 8 Boosters, 40 BasicLands +MBS: 9 Boosters, 80 BasicLands MBS +NPH: 9 Boosters, 80 BasicLands NPH +M12: 9 Boosters, 80 BasicLands +ISD: 9 Boosters, 70 BasicLands +DKA: 9 Boosters, 70 BasicLands ISD +AVR: 9 Boosters, 80 BasicLands +M13: 9 Boosters, 80 BasicLands +RTR: 9 Boosters, 80 BasicLands +GTC: 9 Boosters, 80 BasicLands RTR +DGM: 9 Boosters, 80 BasicLands RTR \ No newline at end of file diff --git a/res/blockdata/setdata.txt b/res/blockdata/setdata.txt index 999c6a8cd4a..092542003f1 100644 --- a/res/blockdata/setdata.txt +++ b/res/blockdata/setdata.txt @@ -95,4 +95,6 @@ Code2:GTC|Code3:GTC|Type:Expansion|Name:Gatecrash Code2:VAN|Code3:VAN|Type:Other|Name:Vanguard Code2:ARC|Code3:ARC|Type:Other|Name:Archenemy - +Code2:DDC|Code3:DDC|Type:Other|Name:Divine vs. Demonic +Code2:PD2|Code3:PD2|Type:Other|Name:Fire and Lightning +Code2:EVG|Code3:EVG|Type:Other|Name:Elves vs. Goblins diff --git a/res/blockdata/starters.txt b/res/blockdata/starters.txt index 5b49156a19d..d03e8003d42 100644 --- a/res/blockdata/starters.txt +++ b/res/blockdata/starters.txt @@ -1,22 +1,22 @@ -Set:LEA|Commons:23|Uncommons:13|Rares:2|BasicLands:22 -Set:LEB|Commons:23|Uncommons:13|Rares:2|BasicLands:22 -Set:2ED|Commons:23|Uncommons:13|Rares:2|BasicLands:22 -Set:3ED|Commons:23|Uncommons:13|Rares:2|BasicLands:22 -Set:4ED|Commons:26|Uncommons:9|Rares:3|BasicLands:22 -Set:ICE|Commons:26|Uncommons:9|Rares:3|BasicLands:22 -Set:5ED|Commons:26|Uncommons:9|Rares:3|BasicLands:22 -Set:MIR|Commons:25|Uncommons:10|Rares:3|BasicLands:22 -Set:TMP|Commons:25|Uncommons:10|Rares:3|BasicLands:22 -Set:USG|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:6ED|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:MMQ|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:INV|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:ODY|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:ONS|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:MRD|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:CHK|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:RAV|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:TSP|Commons:29|Uncommons:10|Rares:3|BasicLands:30|Special:3 -Set:LRW|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:SHM|Commons:32|Uncommons:10|Rares:3|BasicLands:30 -Set:ALA|Commons:32|Uncommons:10|Rares:3|BasicLands:30 \ No newline at end of file +LEA: 23 Common, 13 Uncommon, 2 Rare, 22 BasicLand +LEB: 23 Common, 13 Uncommon, 2 Rare, 22 BasicLand +2ED: 23 Common, 13 Uncommon, 2 Rare, 22 BasicLand +3ED: 23 Common, 13 Uncommon, 2 Rare, 22 BasicLand +4ED: 26 Common, 9 Uncommon, 3 Rare, 22 BasicLand +ICE: 26 Common, 9 Uncommon, 3 Rare, 22 BasicLand +5ED: 26 Common, 9 Uncommon, 3 Rare, 22 BasicLand +MIR: 25 Common, 10 Uncommon, 3 Rare, 22 BasicLand +TMP: 25 Common, 10 Uncommon, 3 Rare, 22 BasicLand +USG: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +6ED: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +MMQ: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +INV: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +ODY: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +ONS: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +MRD: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +CHK: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +RAV: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +TSP: 29 Common, 10 Uncommon, 3 Rare, 3 Special, 30 BasicLand +LRW: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +SHM: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand +ALA: 32 Common, 10 Uncommon, 3 Rare, 30 BasicLand diff --git a/src/main/java/forge/card/BoosterData.java b/src/main/java/forge/card/BoosterData.java deleted file mode 100644 index bc975acd47c..00000000000 --- a/src/main/java/forge/card/BoosterData.java +++ /dev/null @@ -1,162 +0,0 @@ -package forge.card; - -import com.google.common.base.Predicate; - -import forge.item.CardPrinted; -import forge.item.IPaperCard; -import forge.util.FileSection; -import forge.util.storage.StorageReaderFile; - -public class BoosterData extends PackData { - private final int nCommon; - private final int nUncommon; - private final int nRare; - private final int nSpecial; - private final int nDoubleFaced; - private final int foilRate; - private final int artIndices; - private static final int CARDS_PER_BOOSTER = 15; - - public BoosterData(String edition, String editionLand, int nC, int nU, int nR, int nS, int nDF, int artIndices) { - // if this booster has more that 10 cards, there must be a land in - // 15th slot unless it's already taken - this(edition, editionLand, nC, nU, nR, nS, nDF, artIndices, - (nC + nR + nU + nS + nDF) > 10 ? BoosterData.CARDS_PER_BOOSTER - nC - nR - nU - nS - nDF : 0, 68); - } - - public BoosterData(String edition, String editionLand, int nC, int nU, int nR, int nS, int nDF, int artIndices0, int nL, int oneFoilPer) { - super(edition, editionLand, nL > 0 ? nL : 0); - this.nCommon = nC; - this.nUncommon = nU; - this.nRare = nR; - this.nSpecial = nS; - this.nDoubleFaced = nDF; - this.foilRate = oneFoilPer; - artIndices = artIndices0; - } - - public final Predicate getEditionFilter() { - return IPaperCard.Predicates.printedInSets(getEdition()); - } - - public final Predicate getLandEditionFilter() { - return IPaperCard.Predicates.printedInSets(getLandEdition()); - } - - public final int getCommon() { - return this.nCommon; - } - - public final int getUncommon() { - return this.nUncommon; - } - - public final int getRare() { - return this.nRare; - } - - public final int getSpecial() { - return this.nSpecial; - } - - public final int getDoubleFaced() { - return this.nDoubleFaced; - } - - public final int getTotal() { - return this.nCommon + this.nUncommon + this.nRare + this.nSpecial + this.nDoubleFaced + getCntLands(); - } - - public final int getFoilChance() { - return this.foilRate; - } - - public int getArtIndices() { - return artIndices; - } - - private void _append(StringBuilder s, int val, String name) { - if (0 >= val) { - return; - } - s.append(val).append(' ').append(name); - if (1 < val) { - s.append('s'); - } - s.append(", "); - } - - @Override - public String toString() { - int total = getTotal(); - - if (0 >= total) { - return "no cards"; - } - - StringBuilder s = new StringBuilder(); - - _append(s, total, "card"); - if (0 < total) { - // remove comma - s.deleteCharAt(s.length() - 2); - } - - s.append("consisting of "); - _append(s, nSpecial, "special"); - _append(s, nDoubleFaced, "double faced card"); - _append(s, nRare, "rare"); - _append(s, nUncommon, "uncommon"); - _append(s, nCommon, "common"); - if (getEdition().equalsIgnoreCase(getLandEdition())) { - _append(s, getCntLands(), "land"); - } else if (0 < getCntLands()) { - s.append(getCntLands()).append("land"); - if (1 < getCntLands()) { - s.append("s"); - } - s.append("from edition: ").append(getLandEdition()).append(", "); - } - - // trim the last comma and space - s.replace(s.length() - 2, s.length(), ""); - - // put an 'and' before the previous comma - int lastCommaIdx = s.lastIndexOf(","); - if (0 < lastCommaIdx) { - s.replace(lastCommaIdx+1, lastCommaIdx+1, " and"); - } - - if (0 < foilRate) { - s.append(", with a foil rate of 1 in ").append(foilRate); - } - - return s.toString(); - } - - public static final class Reader extends StorageReaderFile { - public Reader(String pathname) { - super(pathname, BoosterData.FN_GET_CODE); - } - - @Override - protected BoosterData read(String line, int i) { - final FileSection section = FileSection.parse(line, ":", "|"); - int nC = section.getInt("Commons", 0); - int nU = section.getInt("Uncommons", 0); - int nR = section.getInt("Rares", 0); - int nS = section.getInt("Special", 0); - int nDf = section.getInt("DoubleFaced", 0); - int artIndices = section.getInt("Images", 1); - int nLand = section.getInt("BasicLands", 0); - int nFoilRate = section.getInt("FoilRate", 68); - String edition = section.get("Set"); - String editionLand = section.get("LandSet"); - if (editionLand == null) { - editionLand = edition; - } - - return new BoosterData(edition, editionLand, nC, nU, nR, nS, nDf, artIndices, nLand, nFoilRate); - } - } -} diff --git a/src/main/java/forge/card/BoosterGenerator.java b/src/main/java/forge/card/BoosterGenerator.java index fbbb3362cc3..871000104bd 100644 --- a/src/main/java/forge/card/BoosterGenerator.java +++ b/src/main/java/forge/card/BoosterGenerator.java @@ -18,20 +18,24 @@ package forge.card; import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import com.google.common.base.Function; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; + + import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import forge.item.CardDb; import forge.item.CardPrinted; -import forge.item.ItemPoolView; -import forge.util.MyRandom; +import forge.item.IPaperCard; +import forge.item.PrintSheet; +import forge.util.TextUtil; /** *

@@ -42,272 +46,147 @@ import forge.util.MyRandom; * @version $Id$ */ public class BoosterGenerator { - private static final int BOOSTERS_TO_FIND_MYTHIC = 8; - - // Function to open a booster as it is. - /** The Constant IDENTITY_PICK. */ - public static final Function> IDENTITY_PICK = new Function>() { - @Override - public List apply(final BoosterGenerator arg1) { - return arg1.getBoosterPack(10, 3, 1, 0, 0, 0, 0, 0, 1); - } - }; - - // These lists are to hold cards grouped by rarity in advance. - - private final List allButLands = new ArrayList(); - - private final Map> cardsByRarity = new EnumMap>(CardRarity.class); - private final Map> twoFacedByRarity = new EnumMap>(CardRarity.class); - private final Map> singleFacedByRarity = new EnumMap>(CardRarity.class); - - // private List commonCreatures; - // private List commonNonCreatures; - - private static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList(0)); - - private BoosterGenerator() { - for (CardRarity v : CardRarity.values()) { - twoFacedByRarity.put(v, new ArrayList()); - singleFacedByRarity.put(v, new ArrayList()); - } + private final static Map cachedSheets = new HashMap(); + private static final synchronized PrintSheet getPrintSheet(String key) { + if( !cachedSheets.containsKey(key) ) + cachedSheets.put(key, makeSheet(key, CardDb.instance().getAllCards())); + return cachedSheets.get(key); } - private void mergeAllFacedCards() { - for (CardRarity v : CardRarity.values()) { - List cp = new ArrayList(singleFacedByRarity.get(v)); - cp.addAll(twoFacedByRarity.get(v)); - cardsByRarity.put(v, cp); - } - } + public static final List getBoosterPack(SealedProductTemplate booster) { + List result = new ArrayList(); + for(Pair slot : booster.getSlots()) { + String slotType = slot.getLeft(); // add expansion symbol here? + int numCards = slot.getRight().intValue(); - /** - *

- * Constructor for BoosterGenerator. - *

- * - * @param cards - * the cards - */ - public BoosterGenerator(final Iterable cards) { - this(); - for (final CardPrinted c : cards) { - this.addToRarity(c); - } - mergeAllFacedCards(); - } + String[] sType = TextUtil.splitWithParenthesis(slotType, ' ', '(', ')'); + String sheetKey = sType.length == 1 ? slotType.trim() + " " + booster.getEdition() : slotType.trim(); - /** - * Instantiates a new booster generator. - * - * @param dPool - * the d pool - */ - public BoosterGenerator(final ItemPoolView dPool) { - this(); - for (final Entry e : dPool) { - this.addToRarity(e.getKey()); - } - mergeAllFacedCards(); - } - - /** - *

- * Constructor for BoosterGenerator. - *

- * - * @param filter - * the card set - */ - public BoosterGenerator(Predicate filter) { - this(); - - for (final CardPrinted c : Iterables.filter(CardDb.instance().getAllCards(), filter)) { - this.addToRarity(c); - // System.out.println(c); - } - mergeAllFacedCards(); - // System.out.println("done"); - } - - private List pickRandomCards(final List source, final int count) { - return this.pickRandomCards(source, count, false); - } - - private List pickRandomCards(final List source, final int count, final boolean singleton) { - int listSize = source == null ? 0 : source.size(); - if ((count <= 0) || (listSize == 0)) { - return BoosterGenerator.EMPTY_LIST; - } - final List result = new ArrayList(count); - - int index = Integer.MAX_VALUE; - for (int iCard = 0; iCard < count; iCard++) { - if (index >= listSize) { - Collections.shuffle(source, MyRandom.getRandom()); - index = 0; - } - result.add(source.get(index)); - - if (!singleton) { - index++; - } else { - source.remove(index); - listSize--; - } + PrintSheet ps = getPrintSheet(sheetKey); + result.addAll(ps.random(numCards, true)); } return result; } - private List pickRandomRaresOrMythics(final List rares, final List mythics, - final int count) { - final int raresSize = rares == null ? 0 : rares.size(); - final int mythicsSize = mythics == null ? 0 : mythics.size(); - if ((count <= 0) || (raresSize == 0)) { - return BoosterGenerator.EMPTY_LIST; - } + // If they request cards from an arbitrary pool, there's no use to cache printsheets. + public static final List getBoosterPack(SealedProductTemplate booster, Iterable sourcePool) { + if(sourcePool == CardDb.instance().getAllCards()) + throw new IllegalArgumentException("Do not use this overload to obtain boosters based on complete cardDb"); + + List result = new ArrayList(); + for(Pair slot : booster.getSlots()) { + String slotType = slot.getLeft(); // add expansion symbol here? + int numCards = slot.getRight().intValue(); - final List result = new ArrayList(count); + String[] sType = TextUtil.splitWithParenthesis(slotType, ' ', '(', ')'); + String sheetKey = sType.length == 1 ? slotType.trim() + " " + booster.getEdition() : slotType.trim(); - int indexRares = Integer.MAX_VALUE; - int indexMythics = Integer.MAX_VALUE; - for (int iCard = 0; iCard < count; iCard++) { - final int rollD8 = MyRandom.getRandom().nextInt(BOOSTERS_TO_FIND_MYTHIC); - final boolean takeMythic = (mythicsSize > 0) && (rollD8 < 1); - if (takeMythic) { - if (indexMythics >= mythicsSize) { - Collections.shuffle(mythics, MyRandom.getRandom()); - indexMythics = 0; - } - result.add(mythics.get(indexMythics)); - indexMythics++; - } else { - if (indexRares >= raresSize) { - Collections.shuffle(rares, MyRandom.getRandom()); - indexRares = 0; - } - result.add(rares.get(indexRares)); - indexRares++; - } + PrintSheet ps = makeSheet(sheetKey, sourcePool); + result.addAll(ps.random(numCards, true)); } return result; - } + } + + @SuppressWarnings("unchecked") + private static final PrintSheet makeSheet(String sheetKey, Iterable src) { + PrintSheet ps = new PrintSheet(); + String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', '(', ')', 2); + + String[] operators = TextUtil.splitWithParenthesis(sKey[0], ':', '(', ')'); + Predicate extraPred = buildExtraPredicate(operators); + String mainCode = operators[0].trim(); + if(mainCode.endsWith("s")) + mainCode = mainCode.substring(0, mainCode.length()-1); - /** - * Gets the singleton booster pack. - * Singleton means that every card in every booster in whole draft is unique! - * First arg in pickRandomCards can't be copy, because picker must remove card from pool to ensure uniqueness. - * - * @param nAnyCard - * the n any card - * @return the singleton booster pack - */ - public final List getSingletonBoosterPack(final int nAnyCard) { - return this.pickRandomCards(allButLands, nAnyCard, true); - } + String sets = sKey[1]; + Predicate setPred = IPaperCard.Predicates.printedInSets(sets.split(" ")); - /** - * Gets the booster pack. - * - * @return the booster pack - */ - public final List getBoosterPack(BoosterData booster) { - return this.getBoosterPack(booster.getCommon(), booster.getUncommon(), booster.getRare(), 0, 0, booster.getSpecial(), - booster.getDoubleFaced(), 0, booster.getCntLands()); - } + // Pre-defined sheets: + if( mainCode.equalsIgnoreCase("any") ) { + Predicate predicate = Predicates.and(setPred, extraPred); + ps.addAll(Iterables.filter(src, predicate)); - /** - * Gets the booster pack. - * - * @param numbers the numbers - * @param nRareSlots the n rare slots - * @param nDoubls the n doubls - * @param nAnyCard the n any card - * @return the booster pack - */ - public final List getBoosterPack(final Map numbers, - final int nRareSlots, final int nDoubls, final int nAnyCard) { - return getBoosterPack(numbers.get(CardRarity.Common), numbers.get(CardRarity.Uncommon), nRareSlots, - numbers.get(CardRarity.Rare), numbers.get(CardRarity.MythicRare), numbers.get(CardRarity.Special), - nDoubls, nAnyCard, numbers.get(CardRarity.BasicLand)); - } + } else if( mainCode.equalsIgnoreCase("common") ) { + Predicate predicate = Predicates.and(setPred, IPaperCard.Predicates.Presets.IS_COMMON, extraPred); + ps.addAll(Iterables.filter(src, predicate)); + } else if ( mainCode.equalsIgnoreCase("uncommon") ) { + Predicate predicate = Predicates.and(setPred, IPaperCard.Predicates.Presets.IS_UNCOMMON, extraPred); + ps.addAll(Iterables.filter(src, predicate)); - /** - * So many parameters are needed for custom limited cardpools,. - * - * @param nCom - * the n com - * @param nUnc - * the n unc - * @param nRareSlots - * the n rare slots - * @param nRares - * the n rares - * @param nMythics - * the n mythics - * @param nSpecs - * the n specs - * @param nDoubls - * the n doubls - * @param nAnyCard - * the n any card - * @param nLands - * the n lands - * @return the booster pack - */ - public final List getBoosterPack(final int nCom, final int nUnc, final int nRareSlots, - final int nRares, final int nMythics, final int nSpecs, final int nDoubls, final int nAnyCard, - final int nLands) { + } else if ( mainCode.equalsIgnoreCase("uncommonrare") ) { // for sets like ARN, where U1 cards are considered rare and U3 are uncommon - final List temp = new ArrayList(); - final Map> commonCardsMap = nDoubls != 0 ? singleFacedByRarity : cardsByRarity; + Predicate predicateRares = Predicates.and(setPred, IPaperCard.Predicates.Presets.IS_RARE, extraPred); + ps.addAll(Iterables.filter(src, predicateRares)); + + Predicate predicateUncommon = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_UNCOMMON, extraPred); + ps.addAll(Iterables.filter(src, predicateUncommon), 3); - temp.addAll(this.pickRandomCards(commonCardsMap.get(CardRarity.Common), nCom)); - temp.addAll(this.pickRandomCards(commonCardsMap.get(CardRarity.Uncommon), nUnc)); + } else if ( mainCode.equalsIgnoreCase("rare") ) { + Predicate predicateMythic = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_MYTHIC_RARE, extraPred); + ps.addAll(Iterables.filter(src, predicateMythic)); + + Predicate predicateRare = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_RARE, extraPred); + ps.addAll(Iterables.filter(src, predicateRare), 2); + + } else if ( mainCode.equalsIgnoreCase("rarenotmythic") ) { + Predicate predicateRare = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_RARE, extraPred); + ps.addAll(Iterables.filter(src, predicateRare)); + + } else if ( mainCode.equalsIgnoreCase("mythic") ) { + Predicate predicateMythic = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_MYTHIC_RARE, extraPred); + ps.addAll(Iterables.filter(src, predicateMythic)); - if (nRareSlots > 0) { - temp.addAll(this.pickRandomRaresOrMythics(commonCardsMap.get(CardRarity.Rare), - cardsByRarity.get(CardRarity.MythicRare), nRareSlots)); + } else if ( mainCode.equalsIgnoreCase("basicland") ) { + Predicate predicateLand = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_BASIC_LAND, extraPred ); + ps.addAll(Iterables.filter(src, predicateLand)); + + } else if ( mainCode.equalsIgnoreCase("timeshifted") ) { + Predicate predicate = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_SPECIAL, extraPred ); + ps.addAll(Iterables.filter(src, predicate)); + + } else if ( mainCode.equalsIgnoreCase("mazeland") ) { + } - if ((nRares > 0) || (nMythics > 0)) { - if (nMythics == 0) { - temp.addAll(this.pickRandomRaresOrMythics(commonCardsMap.get(CardRarity.Rare), - cardsByRarity.get(CardRarity.MythicRare), nRares)); - } else { - temp.addAll(this.pickRandomCards(commonCardsMap.get(CardRarity.Rare), nRares)); - temp.addAll(this.pickRandomCards(commonCardsMap.get(CardRarity.MythicRare), nMythics)); - } - } - if (nDoubls > 0) { - final int dblFacedRarity = MyRandom.getRandom().nextInt(nCom + nUnc + nRareSlots); - CardRarity rarityInSlot = CardRarity.MythicRare; - if (dblFacedRarity < nCom) { - rarityInSlot = CardRarity.Common; - } else if (dblFacedRarity < nCom + nUnc) { - rarityInSlot = CardRarity.Uncommon; - } else if (MyRandom.getRandom().nextInt(BOOSTERS_TO_FIND_MYTHIC) != 0) { - rarityInSlot = CardRarity.Rare; + return ps; + } + + /** + * TODO: Write javadoc for this method. + * @param operators + * @return + */ + private static Predicate buildExtraPredicate(String[] operators) { + if ( operators.length == 0) + return Predicates.alwaysTrue(); + + List> conditions = new ArrayList>(); + for(int i = 1; i < operators.length; i++) { + String operator = operators[i]; + if(StringUtils.isEmpty(operator)) + continue; + + boolean invert = operator.charAt(0) == '!'; + if( invert ) operator = operator.substring(1); + + Predicate toAdd = null; + if( operator.equals("dfc") ) { + toAdd = Predicates.compose(CardRulesPredicates.splitType(CardSplitType.Transform), CardPrinted.FN_GET_RULES); + } else if ( operator.startsWith("name(") ) { + operator = StringUtils.strip(operator.substring(4), "() "); + String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"'); + toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames)); } - temp.addAll(this.pickRandomCards(twoFacedByRarity.get(rarityInSlot), nDoubls)); - } - - temp.addAll(this.pickRandomCards(commonCardsMap.get(CardRarity.Special), nSpecs)); - temp.addAll(this.pickRandomCards(this.allButLands, nAnyCard)); - temp.addAll(this.pickRandomCards(commonCardsMap.get(CardRarity.BasicLand), nLands)); - - return temp; - } - - private void addToRarity(final CardPrinted c) { - - Map> targetList = c.getRules().getSplitType() == CardSplitType.Transform ? twoFacedByRarity : singleFacedByRarity; - targetList.get(c.getRarity()).add(c); - - if (!c.getRules().getType().isBasicLand()) { - this.allButLands.add(c); + if(toAdd == null) + throw new IllegalArgumentException("Booster generator: operator could not be parsed - " + operator); + + if( invert ) + toAdd = Predicates.not(toAdd); + conditions.add(toAdd); } + return Predicates.and(conditions); } + } diff --git a/src/main/java/forge/card/BoosterTemplate.java b/src/main/java/forge/card/BoosterTemplate.java new file mode 100644 index 00000000000..d27e558ad2f --- /dev/null +++ b/src/main/java/forge/card/BoosterTemplate.java @@ -0,0 +1,101 @@ +package forge.card; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; + +import forge.util.TextUtil; +import forge.util.storage.StorageReaderFile; + +public class BoosterTemplate extends SealedProductTemplate { + + @SuppressWarnings("unchecked") + public final static BoosterTemplate genericBooster = new BoosterTemplate(null, 1, Lists.newArrayList( + Pair.of("Common", 10), Pair.of("Uncommon", 3), Pair.of("Rare", 1), Pair.of("BasicLand", 1) + )); + + private final int foilRate = 68; + private final int artIndices; + private final String edition; + + private BoosterTemplate(String edition0, int artIndices0, Iterable> itrSlots) { + super(itrSlots); + this.edition = edition0; + artIndices = artIndices0; + } + + public final int getFoilChance() { + return this.foilRate; + } + + public int getArtIndices() { + return artIndices; + } + + @Override + public final String getEdition() { return edition; } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + + + s.append("consisting of "); + for(Pair p : slots) { + s.append(p.getRight()).append(" ").append(p.getLeft()).append(", "); + } + + // trim the last comma and space + s.replace(s.length() - 2, s.length(), ""); + + // put an 'and' before the previous comma + int lastCommaIdx = s.lastIndexOf(","); + if (0 < lastCommaIdx) { + s.replace(lastCommaIdx+1, lastCommaIdx+1, " and"); + } + + if (0 < foilRate) { + s.append(", with a foil rate of 1 in ").append(foilRate); + } + + return s.toString(); + } + + public static final Function FN_GET_CODE = new Function() { + @Override + public String apply(BoosterTemplate arg1) { + return arg1.edition; + } + }; + + + public static final class Reader extends StorageReaderFile { + public Reader(String pathname) { + super(pathname, BoosterTemplate.FN_GET_CODE); + } + + @Override + protected BoosterTemplate read(String line, int i) { + String[] headAndData = TextUtil.split(line, ':', 2); + final String edition = headAndData[0]; + final String[] data = TextUtil.splitWithParenthesis(headAndData[1], ',', '(', ')'); + int nCovers = 1; + + List> slots = new ArrayList>(); + for(String slotDesc : data) { + String[] kv = TextUtil.splitWithParenthesis(slotDesc, ' ', '(', ')', 2); + if (kv[1].startsWith("cover")) + nCovers = Integer.parseInt(kv[0]); + else + slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0]))); + } + + return new BoosterTemplate(edition, nCovers, slots); + } + } +} diff --git a/src/main/java/forge/card/CardBlock.java b/src/main/java/forge/card/CardBlock.java index 3ff4691e6b7..ceaa398339e 100644 --- a/src/main/java/forge/card/CardBlock.java +++ b/src/main/java/forge/card/CardBlock.java @@ -22,7 +22,6 @@ import java.util.List; import com.google.common.base.Function; import com.google.common.base.Predicate; - import forge.item.CardPrinted; import forge.item.IPaperCard; import forge.util.storage.StorageReaderFile; diff --git a/src/main/java/forge/card/CardRulesPredicates.java b/src/main/java/forge/card/CardRulesPredicates.java index 855b95e91b9..a555c62dfb6 100644 --- a/src/main/java/forge/card/CardRulesPredicates.java +++ b/src/main/java/forge/card/CardRulesPredicates.java @@ -6,7 +6,6 @@ import java.util.List; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; - import forge.util.ComparableOp; import forge.util.PredicateString; @@ -98,6 +97,15 @@ public final class CardRulesPredicates { return new LeafString(LeafString.CardField.NAME, op, what); } + /** + * TODO: Write javadoc for this method. + * @param transform + * @return + */ + public static Predicate splitType(CardSplitType transform) { + return new PredicateSplitType(transform); + } + /** * Sub type. * @@ -446,6 +454,19 @@ public final class CardRulesPredicates { return false; } } + + private static class PredicateSplitType implements Predicate { + private final CardSplitType cst; + + public PredicateSplitType(final CardSplitType type) { + cst = type; + } + + @Override + public boolean apply(final CardRules subject) { + return subject.getSplitType() == cst; + } + } /** * The Class Presets. diff --git a/src/main/java/forge/card/FatPackData.java b/src/main/java/forge/card/FatPackData.java deleted file mode 100644 index c03e038351f..00000000000 --- a/src/main/java/forge/card/FatPackData.java +++ /dev/null @@ -1,65 +0,0 @@ -package forge.card; - -import forge.util.FileSection; -import forge.util.storage.StorageReaderFile; - -/** - * TODO: Write javadoc for this type. - * - */ -public class FatPackData extends PackData { - private final int cntBoosters; - public int getCntBoosters() { - return cntBoosters; - } - - public FatPackData(String edition0, String landEdition0, int nBoosters, int nBasicLands) - { - super(edition0, landEdition0, nBasicLands); - cntBoosters = nBoosters; - } - - public static final class Reader extends StorageReaderFile { - public Reader(String pathname) { - super(pathname, PackData.FN_GET_CODE); - } - - @Override - protected FatPackData read(String line, int i) { - final FileSection section = FileSection.parse(line, ":", "|"); - int nBoosters = section.getInt("Boosters", 0); - int nLand = section.getInt("BasicLands", 0); - return new FatPackData(section.get("Set"), section.get("LandSet"), nBoosters, nLand); - } - } - - @Override - public String toString() { - if (0 >= cntBoosters) { - return "no cards"; - } - - StringBuilder s = new StringBuilder(); - - if (0 < getCntLands()) { - s.append(getCntLands()).append(" land"); - if (1 < getCntLands()) { - s.append("s"); - } - - if (!getEdition().equalsIgnoreCase(getLandEdition())) { - s.append(" from edition: ").append(getLandEdition()); - } - - if (0 < cntBoosters) { - s.append(" and "); - } - } - - if (0 < cntBoosters) { - s.append(cntBoosters).append(" booster packs, each containing "); - } - - return s.toString(); - } -} diff --git a/src/main/java/forge/card/FatPackTemplate.java b/src/main/java/forge/card/FatPackTemplate.java new file mode 100644 index 00000000000..7f9497f633c --- /dev/null +++ b/src/main/java/forge/card/FatPackTemplate.java @@ -0,0 +1,85 @@ +package forge.card; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.base.Function; + +import forge.util.TextUtil; +import forge.util.storage.StorageReaderFile; + +/** + * TODO: Write javadoc for this type. + * + */ +public class FatPackTemplate extends SealedProductTemplate { + private final int cntBoosters; + private final String edition; + + @Override + public String getEdition() { return edition; } + public int getCntBoosters() { return cntBoosters; } + + public static final Function FN_GET_CODE = new Function() { + @Override + public String apply(FatPackTemplate arg1) { + return arg1.edition; + } + }; + + private FatPackTemplate(String edition0, int boosters, Iterable> itrSlots) + { + super(itrSlots); + edition = edition0; + cntBoosters = boosters; + } + + public static final class Reader extends StorageReaderFile { + public Reader(String pathname) { + super(pathname, FatPackTemplate.FN_GET_CODE); + } + + @Override + protected FatPackTemplate read(String line, int i) { + String[] headAndData = TextUtil.split(line, ':', 2); + final String edition = headAndData[0]; + final String[] data = TextUtil.splitWithParenthesis(headAndData[1], ',', '(', ')'); + int nBoosters = 6; + + List> slots = new ArrayList>(); + for(String slotDesc : data) { + String[] kv = TextUtil.split(slotDesc, ' ', 2); + if (kv[1].startsWith("Booster")) + nBoosters = Integer.parseInt(kv[0]); + else + slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0]))); + } + + return new FatPackTemplate(edition, nBoosters, slots); + } + } + + @Override + public String toString() { + if (0 >= cntBoosters) { + return "no cards"; + } + + StringBuilder s = new StringBuilder(); + for(Pair p : slots) { + s.append(p.getRight()).append(" ").append(p.getLeft()).append(", "); + } + // trim the last comma and space + s.replace(s.length() - 2, s.length(), ""); + + s.append(" and "); + if (0 < cntBoosters) { + s.append(cntBoosters).append(" booster packs"); + } + + return s.toString(); + } +} diff --git a/src/main/java/forge/card/MetaSet.java b/src/main/java/forge/card/MetaSet.java index 33c0652279d..7da165aead1 100644 --- a/src/main/java/forge/card/MetaSet.java +++ b/src/main/java/forge/card/MetaSet.java @@ -22,8 +22,6 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import com.google.common.base.Function; - import forge.Singletons; import forge.game.limited.CustomLimited; import forge.item.CardDb; @@ -189,8 +187,7 @@ public class MetaSet { final File dFolder = new File("res/sealed/"); if (!dFolder.exists()) { - throw new RuntimeException("GenerateSealed : folder not found -- folder is " - + dFolder.getAbsolutePath()); + throw new RuntimeException("GenerateSealed : folder not found -- folder is " + dFolder.getAbsolutePath()); } if (!dFolder.isDirectory()) { @@ -199,27 +196,12 @@ public class MetaSet { List dfData = FileUtil.readFile("res/sealed/" + data + ".sealed"); final CustomLimited myCube = CustomLimited.parse(dfData, Singletons.getModel().getDecks().getCubes()); - final BoosterGenerator bpCustom = new BoosterGenerator(myCube.getCardPool()); - final Function> fnPick = new Function>() { - @Override - public List apply(final BoosterGenerator pack) { - if (myCube.getIgnoreRarity()) { - if (!myCube.getSingleton()) { - return pack.getBoosterPack(0, 0, 0, 0, 0, 0, 0, myCube.getNumCards(), 0); - } else { - return pack.getSingletonBoosterPack(myCube.getNumCards()); - } - } - return pack.getBoosterPack(myCube.getNumbersByRarity(), 0, 0, 0); - } - - }; - - return new UnOpenedProduct(fnPick, bpCustom); + + SealedProductTemplate fnPick = myCube.getIgnoreRarity() ? myCube.getSealedProductTemplate() : BoosterTemplate.genericBooster; + return new UnOpenedProduct(fnPick, myCube.getCardPool()); } else if ("full".equalsIgnoreCase(type)) { - final BoosterGenerator bpFull = new BoosterGenerator(CardDb.instance().getUniqueCards()); - return new UnOpenedProduct(BoosterGenerator.IDENTITY_PICK, bpFull); + return new UnOpenedProduct(BoosterTemplate.genericBooster); } else if ("meta".equalsIgnoreCase(type)) { @@ -230,11 +212,9 @@ public class MetaSet { if (data.indexOf(aCard.getEdition()) > -1) { cardPool.add(aCard); // System.out.println("Added card" + aCard.getName()); - } + } } - - final BoosterGenerator bpSets = new BoosterGenerator(cardPool); - return new UnOpenedProduct(BoosterGenerator.IDENTITY_PICK, bpSets); + return new UnOpenedProduct(BoosterTemplate.genericBooster, cardPool); } else if ("booster".equalsIgnoreCase(type)) { return new UnOpenedProduct(Singletons.getModel().getBoosters().get(data)); } else if ("pack".equalsIgnoreCase(type)) { @@ -244,8 +224,8 @@ public class MetaSet { } else if ("random1".equalsIgnoreCase(type)) { return new UnOpenedMeta(data, false); } else if ("combo".equalsIgnoreCase(type)) { - final BoosterGenerator bpSets = new BoosterGenerator(buildPool(data)); - return new UnOpenedProduct(BoosterGenerator.IDENTITY_PICK, bpSets); + final BoosterGenerator bpSets = new BoosterGenerator(); + return new UnOpenedProduct(BoosterTemplate.genericBooster, buildPool(data)); } else { throw new RuntimeException("Cannot initialize boosters for: " + type); diff --git a/src/main/java/forge/card/PackData.java b/src/main/java/forge/card/PackData.java deleted file mode 100644 index 5f2ab9b5eb0..00000000000 --- a/src/main/java/forge/card/PackData.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Forge: Play Magic: the Gathering. - * Copyright (C) 2011 Forge Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package forge.card; - -import org.apache.commons.lang.NullArgumentException; - -import com.google.common.base.Function; - -public class PackData { - private final String edition; - private final String landEdition; - private final int cntLands; - - public final String getEdition() { - return edition; - } - - public final String getLandEdition() { - return landEdition == null ? edition : landEdition; - } - - public int getCntLands() { - return cntLands; - } - - public PackData(String edition0, String landEdition0, int nBasicLands) - { - if (null == edition0) { throw new NullArgumentException("edition0"); } - edition = edition0; - landEdition = landEdition0; - cntLands = nBasicLands; - } - - public static final Function FN_GET_CODE = new Function() { - @Override - public String apply(PackData arg1) { - return arg1.edition; - } - }; - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (this.getClass() != obj.getClass()) { - return false; - } - PackData other = (PackData)obj; - return edition.equals(other.edition); - } - - @Override - public int hashCode() { - return edition.hashCode(); - } -} diff --git a/src/main/java/forge/card/SealedProductTemplate.java b/src/main/java/forge/card/SealedProductTemplate.java new file mode 100644 index 00000000000..c04953ca35b --- /dev/null +++ b/src/main/java/forge/card/SealedProductTemplate.java @@ -0,0 +1,57 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package forge.card; + +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.collect.Lists; + +public class SealedProductTemplate { + + protected final List> slots; + + + public String getEdition() { + return null; + } + + public final List> getSlots() { + return slots; + } + + public SealedProductTemplate(Iterable> itrSlots) + { + slots = Lists.newArrayList(itrSlots); + } + + @SuppressWarnings("unchecked") + public SealedProductTemplate(int qty) { + this(Lists.newArrayList(Pair.of("any", qty))); + } + + public int getTotal() { + int sum = 0; + for(Pair p : slots) { + sum += p.getRight().intValue(); + } + return sum; + } +} diff --git a/src/main/java/forge/card/UnOpenedMeta.java b/src/main/java/forge/card/UnOpenedMeta.java index 0379a31fb79..42536c525ac 100644 --- a/src/main/java/forge/card/UnOpenedMeta.java +++ b/src/main/java/forge/card/UnOpenedMeta.java @@ -100,7 +100,7 @@ public class UnOpenedMeta extends UnOpenedProduct { * @return List, list of cards. */ @Override - public List open() { + public List get() { return this.open(true, null); } @@ -112,7 +112,7 @@ public class UnOpenedMeta extends UnOpenedProduct { * known partialities for the AI. * @return List, list of cards. */ - @Override + public List open(final boolean isHuman, List partialities) { if (metaSets.size() < 1) { @@ -132,7 +132,7 @@ public class UnOpenedMeta extends UnOpenedProduct { for (int i = 0; i < metaSets.size(); i++) { if (o.toString().equals(metaSets.get(i).getCode())) { final UnOpenedProduct newBooster = metaSets.get(i).getBooster(); - return newBooster.open(); + return newBooster.get(); } } @@ -168,7 +168,7 @@ public class UnOpenedMeta extends UnOpenedProduct { // System.out.println("AI chose " + metaSets.get(selected).getCode() + " because partiality not established or failed percentage test."); } final UnOpenedProduct newBooster = metaSets.get(selected).getBooster(); - return newBooster.open(); + return newBooster.get(); } } else { @@ -183,7 +183,7 @@ public class UnOpenedMeta extends UnOpenedProduct { // System.out.println("AI decided to add " + metaSets.get(selected).getCode() + " to partialities."); } final UnOpenedProduct newBooster = metaSets.get(selected).getBooster(); - return newBooster.open(); + return newBooster.get(); } } } diff --git a/src/main/java/forge/card/UnOpenedProduct.java b/src/main/java/forge/card/UnOpenedProduct.java index bc054f09c7c..e5bf921553c 100644 --- a/src/main/java/forge/card/UnOpenedProduct.java +++ b/src/main/java/forge/card/UnOpenedProduct.java @@ -2,50 +2,48 @@ package forge.card; import java.util.List; -import com.google.common.base.Function; +import com.google.common.base.Supplier; import forge.item.CardPrinted; +import forge.item.ItemPoolView; /** * TODO: Write javadoc for this type. * */ -public class UnOpenedProduct { - - private final Function> openBooster; - private final BoosterGenerator generator; - private final BoosterData booster; - - public UnOpenedProduct(Function> identityPick, BoosterGenerator bpFull) { - openBooster = identityPick; - generator = bpFull; - booster = null; - } +public class UnOpenedProduct implements Supplier> { + private final ItemPoolView cards; + private final Iterable cardPoolFlat; + private final SealedProductTemplate tpl; /** * TODO: Write javadoc for Constructor. - * @param boosterData */ - public UnOpenedProduct(BoosterData boosterData) { - booster = boosterData; - openBooster = null; - generator = new BoosterGenerator(boosterData.getEditionFilter()); + public UnOpenedProduct(SealedProductTemplate template) { + tpl = template; + cards = null; + cardPoolFlat = null; } - public List open() { - return openBooster != null ? openBooster.apply(generator) : generator.getBoosterPack(booster); + public UnOpenedProduct(SealedProductTemplate template, ItemPoolView pool) { + cards = pool; + cardPoolFlat = null; + tpl = template; } - /** - * Like open, can define whether is human or not. - * @param isHuman - * boolean, is human player? - * @param partialities - * known partialities for the AI. - * @return List, list of cards. + public UnOpenedProduct(SealedProductTemplate template, Iterable pool) { + cardPoolFlat = pool; + tpl = template; + cards = null; + } + + /* (non-Javadoc) + * @see com.google.common.base.Supplier#get() */ - public List open(final boolean isHuman, List partialities) { - return open(); + @Override + public List get() { + return cards == null && cardPoolFlat == null ? BoosterGenerator.getBoosterPack(tpl) + : BoosterGenerator.getBoosterPack(tpl, cardPoolFlat == null ? cards.toFlatList() : cardPoolFlat); } } diff --git a/src/main/java/forge/deck/DeckFormat.java b/src/main/java/forge/deck/DeckFormat.java index bbe88db00e2..d720fb2f15e 100644 --- a/src/main/java/forge/deck/DeckFormat.java +++ b/src/main/java/forge/deck/DeckFormat.java @@ -19,9 +19,7 @@ package forge.deck; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.math.IntRange; diff --git a/src/main/java/forge/game/GameFormat.java b/src/main/java/forge/game/GameFormat.java index 739121e2730..0a2ed6597bf 100644 --- a/src/main/java/forge/game/GameFormat.java +++ b/src/main/java/forge/game/GameFormat.java @@ -78,7 +78,7 @@ public class GameFormat implements Comparable { } private Predicate buildFilterPrinted() { - final Predicate banNames = IPaperCard.Predicates.namesExcept(this.bannedCardNames); + final Predicate banNames = Predicates.not(IPaperCard.Predicates.names(this.bannedCardNames)); if (this.allowedSetCodes == null || this.allowedSetCodes.isEmpty()) { return banNames; } @@ -86,7 +86,7 @@ public class GameFormat implements Comparable { } private Predicate buildFilterRules() { - final Predicate banNames = IPaperCard.Predicates.namesExcept(this.bannedCardNames); + final Predicate banNames = Predicates.not(IPaperCard.Predicates.names(this.bannedCardNames)); if (this.allowedSetCodes == null || this.allowedSetCodes.isEmpty()) { return banNames; } diff --git a/src/main/java/forge/game/limited/BoosterDraft.java b/src/main/java/forge/game/limited/BoosterDraft.java index abbfb7a219f..a4a72d835e1 100644 --- a/src/main/java/forge/game/limited/BoosterDraft.java +++ b/src/main/java/forge/game/limited/BoosterDraft.java @@ -28,14 +28,16 @@ import java.util.TreeMap; import javax.swing.JOptionPane; -import com.google.common.base.Function; +import com.google.common.base.Supplier; import forge.Card; import forge.Constant.Preferences; import forge.Singletons; import forge.card.BoosterGenerator; +import forge.card.BoosterTemplate; import forge.card.CardBlock; import forge.card.CardEdition; +import forge.card.SealedProductTemplate; import forge.card.UnOpenedProduct; import forge.deck.Deck; import forge.gui.GuiChoose; @@ -47,6 +49,7 @@ import forge.item.ItemPoolView; import forge.properties.NewConstants; import forge.util.FileUtil; import forge.util.HttpUtil; +import forge.util.storage.IStorageView; /** * @@ -66,7 +69,7 @@ public final class BoosterDraft implements IBoosterDraft { private final Map draftPicks = new TreeMap(); private final CardPoolLimitation draftFormat; - private final ArrayList product = new ArrayList(); + private final List>> product = new ArrayList>>(); /** *

@@ -82,11 +85,11 @@ public final class BoosterDraft implements IBoosterDraft { switch (draftType) { case Full: // Draft from all cards in Forge - final BoosterGenerator bpFull = new BoosterGenerator(CardDb.instance().getUniqueCards()); - for (int i = 0; i < 3; i++) { - this.product.add(new UnOpenedProduct(BoosterGenerator.IDENTITY_PICK, bpFull)); - } + Supplier> s = new Supplier>() { + @Override public List get() { return BoosterGenerator.getBoosterPack(BoosterTemplate.genericBooster); } + }; + for (int i = 0; i < 3; i++) this.product.add(s); IBoosterDraft.LAND_SET_CODE[0] = CardDb.instance().getCard("Plains").getEdition(); break; @@ -94,26 +97,18 @@ public final class BoosterDraft implements IBoosterDraft { List blocks = new ArrayList(); - if (draftType == CardPoolLimitation.Block) { - for (CardBlock b : Singletons.getModel().getBlocks()) { - if (b.hasMetaSetType("choose1") || b.hasMetaSetType("random1")) { - System.out.println("Ignoring block " + b.getName() + " because its MetaSet types are not supported in Draft."); - } else { - blocks.add(b); - } - } + IStorageView storage = draftType == CardPoolLimitation.Block + ? Singletons.getModel().getBlocks() : Singletons.getModel().getFantasyBlocks(); - } - else { - for (CardBlock b : Singletons.getModel().getFantasyBlocks()) { - if (b.hasMetaSetType("choose1") || b.hasMetaSetType("random1")) { - System.out.println("Ignoring block " + b.getName() + " because its MetaSet types are not supported in Draft."); - } else { - blocks.add(b); - } + for (CardBlock b : storage) { + if (b.hasMetaSetType("choose1") || b.hasMetaSetType("random1")) { + System.out.println("Ignoring block " + b.getName() + " because its MetaSet types are not supported in Draft."); + } else { + blocks.add(b); } } + final CardBlock block = GuiChoose.one("Choose Block", blocks); final CardEdition[] cardSets = block.getSets(); @@ -146,7 +141,8 @@ public final class BoosterDraft implements IBoosterDraft { this.product.add(block.getBooster(pp[i])); } else { - this.product.add(new UnOpenedProduct(Singletons.getModel().getBoosters().get(pp[i]))); + this.product.add( + new UnOpenedProduct(Singletons.getModel().getBoosters().get(pp[i]))); } } } else { @@ -190,22 +186,10 @@ public final class BoosterDraft implements IBoosterDraft { throw new RuntimeException("BoosterGenerator : deck not found"); } - final BoosterGenerator bpCustom = new BoosterGenerator(dPool); - final Function> fnPick = new Function>() { - @Override - public List apply(final BoosterGenerator pack) { - if (draft.getIgnoreRarity()) { - if (!draft.getSingleton()) { - return pack.getBoosterPack(0, 0, 0, 0, 0, 0, 0, draft.getNumCards(), 0); - } - return pack.getSingletonBoosterPack(draft.getNumCards()); - } - return pack.getBoosterPack(draft.getNumbersByRarity(), 0, 0, 0); - } - }; + final SealedProductTemplate tpl = draft.getSealedProductTemplate(); for (int i = 0; i < draft.getNumPacks(); i++) { - this.product.add(new UnOpenedProduct(fnPick, bpCustom)); + this.product.add(new UnOpenedProduct(tpl, dPool)); } IBoosterDraft.LAND_SET_CODE[0] = draft.getLandSetCode(); @@ -268,7 +252,7 @@ public final class BoosterDraft implements IBoosterDraft { final List> list = new ArrayList>(); for (int i = 0; i < 8; i++) { - list.add(this.product.get(this.nextBoosterGroup).open()); + list.add(this.product.get(this.nextBoosterGroup).get()); } this.nextBoosterGroup++; diff --git a/src/main/java/forge/game/limited/CustomLimited.java b/src/main/java/forge/game/limited/CustomLimited.java index b89dc2c7863..07038082a2a 100644 --- a/src/main/java/forge/game/limited/CustomLimited.java +++ b/src/main/java/forge/game/limited/CustomLimited.java @@ -17,11 +17,15 @@ */ package forge.game.limited; -import java.util.EnumMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; -import forge.card.CardRarity; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import forge.card.BoosterTemplate; +import forge.card.SealedProductTemplate; import forge.deck.Deck; import forge.deck.DeckBase; import forge.item.CardDb; @@ -29,6 +33,7 @@ import forge.item.CardPrinted; import forge.item.ItemPool; import forge.item.ItemPoolView; import forge.util.FileSection; +import forge.util.TextUtil; import forge.util.storage.IStorageView; /** @@ -40,14 +45,17 @@ import forge.util.storage.IStorageView; * @version $Id$ */ public class CustomLimited extends DeckBase { - + private final SealedProductTemplate tpl; + /** * TODO: Write javadoc for Constructor. * * @param name0 the name0 + * @param slots */ - public CustomLimited(final String name0) { + public CustomLimited(final String name0, List> slots) { super(name0); + tpl = new SealedProductTemplate(slots); } private static final long serialVersionUID = 7435640939026612173L; @@ -58,10 +66,6 @@ public class CustomLimited extends DeckBase { /** The Singleton. */ private boolean singleton = false; - /** The Num cards. */ - private int numCards = 15; - - private final Map numRarity = new EnumMap(CardRarity.class); /** The Num packs. */ private int numPacks = 3; @@ -71,6 +75,7 @@ public class CustomLimited extends DeckBase { /** The Land set code. */ private String landSetCode = CardDb.instance().getCard("Plains", true).getEdition(); + /* * (non-Javadoc) * @@ -92,48 +97,29 @@ public class CustomLimited extends DeckBase { final FileSection data = FileSection.parse(dfData, ":"); - final CustomLimited cd = new CustomLimited(data.get("Name")); + List> slots = new ArrayList>(); + String boosterData = data.get("Booster"); + if(StringUtils.isNotEmpty(boosterData)){ + final String[] booster = TextUtil.splitWithParenthesis(boosterData, ',', '(', ')'); + for(String slotDesc : booster) { + String[] kv = TextUtil.splitWithParenthesis(slotDesc, ' ', '(', ')', 2); + slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0]))); + } + } else + slots = BoosterTemplate.genericBooster.getSlots(); + + final CustomLimited cd = new CustomLimited(data.get("Name"), slots); cd.setIgnoreRarity(data.getBoolean("IgnoreRarity")); cd.setSingleton(data.getBoolean("Singleton")); - cd.setLandSetCode(data.get("LandSetCode")); - cd.numCards = data.getInt("NumCards", 15); - - cd.numRarity.put(CardRarity.BasicLand, data.getInt("NumBasicLands", 1)); - cd.numRarity.put(CardRarity.Special, data.getInt("NumSpecials")); - cd.numRarity.put(CardRarity.Rare, data.getInt("NumRares", 1)); - cd.numRarity.put(CardRarity.MythicRare, data.getInt("NumMythics")); - cd.numRarity.put(CardRarity.Uncommon, data.getInt("NumUncommons", 3)); - cd.numRarity.put(CardRarity.Common, data.getInt("NumCommons", 10)); - + cd.landSetCode = data.get("LandSetCode"); cd.numPacks = data.getInt("NumPacks"); - - final String deckName = data.get("DeckFile"); - final Deck deckCube = cubes.get(deckName); - cd.cardPool = deckCube == null ? ItemPool.createFrom( - CardDb.instance().getUniqueCards(), CardPrinted.class) - : deckCube.getMain(); + final Deck deckCube = cubes.get(data.get("DeckFile")); + cd.cardPool = deckCube == null ? ItemPool.createFrom(CardDb.instance().getUniqueCards(), CardPrinted.class) : deckCube.getMain(); return cd; } - /** - * Gets the num cards. - * - * @return the numCards - */ - public int getNumCards() { - return this.numCards; - } - /** - * Sets the num cards. - * - * @param numCardsIn - * the numCards to set - */ - public void setNumCards(final int numCardsIn) { - this.numCards = numCardsIn; - } /** * Gets the num packs. @@ -201,16 +187,6 @@ public class CustomLimited extends DeckBase { return this.landSetCode; } - /** - * Sets the land set code. - * - * @param landSetCodeIn - * the landSetCode to set - */ - public void setLandSetCode(final String landSetCodeIn) { - this.landSetCode = landSetCodeIn; - } - /* * (non-Javadoc) * @@ -227,16 +203,14 @@ public class CustomLimited extends DeckBase { */ @Override protected DeckBase newInstance(final String name0) { - return new CustomLimited(name0); + return new CustomLimited(name0, tpl.getSlots()); } /** * TODO: Write javadoc for this method. - * - * @return the numbers by rarity + * @return */ - public Map getNumbersByRarity() { - return this.numRarity; + public SealedProductTemplate getSealedProductTemplate() { + return tpl; } - } diff --git a/src/main/java/forge/game/limited/SealedDeckFormat.java b/src/main/java/forge/game/limited/SealedDeckFormat.java index 86df2c913be..5248bc93c89 100644 --- a/src/main/java/forge/game/limited/SealedDeckFormat.java +++ b/src/main/java/forge/game/limited/SealedDeckFormat.java @@ -23,12 +23,11 @@ import java.util.List; import javax.swing.JOptionPane; -import com.google.common.base.Function; - import forge.Singletons; -import forge.card.BoosterGenerator; +import forge.card.BoosterTemplate; import forge.card.CardBlock; import forge.card.CardEdition; +import forge.card.UnOpenedMeta; import forge.card.UnOpenedProduct; import forge.gui.GuiChoose; import forge.item.CardDb; @@ -65,9 +64,6 @@ public class SealedDeckFormat { partiality = new ArrayList(); if (sealedType.equals("Full")) { - - final BoosterGenerator bpFull = new BoosterGenerator(CardDb.instance().getUniqueCards()); - // Choose number of boosters final Integer[] integers = new Integer[10]; @@ -78,7 +74,7 @@ public class SealedDeckFormat { Integer nrBoosters = GuiChoose.one("How many booster packs?", integers); for (int i = 0; i < nrBoosters; i++) { - this.product.add(new UnOpenedProduct(BoosterGenerator.IDENTITY_PICK, bpFull)); + this.product.add(new UnOpenedProduct(BoosterTemplate.genericBooster)); } this.getLandSetCode()[0] = CardDb.instance().getCard("Plains").getEdition(); @@ -259,7 +255,7 @@ public class SealedDeckFormat { if (element.endsWith(".sealed")) { final List dfData = FileUtil.readFile("res/sealed/" + element); final CustomLimited cs = CustomLimited.parse(dfData, Singletons.getModel().getDecks().getCubes()); - if (cs.getNumCards() > 5) { // Do not allow too small cubes to be played as 'stand-alone'! + if (cs.getSealedProductTemplate().getTotal() > 5) { // Do not allow too small cubes to be played as 'stand-alone'! customs.add(cs); } } @@ -273,20 +269,6 @@ public class SealedDeckFormat { final CustomLimited draft = GuiChoose.one("Choose Custom Sealed Pool", customs); - final BoosterGenerator bpCustom = new BoosterGenerator(draft.getCardPool()); - final Function> fnPick = new Function>() { - @Override - public List apply(final BoosterGenerator pack) { - if (draft.getIgnoreRarity()) { - if (!draft.getSingleton()) { - return pack.getBoosterPack(0, 0, 0, 0, 0, 0, 0, draft.getNumCards(), 0); - } else { - return pack.getSingletonBoosterPack(draft.getNumCards()); - } - } - return pack.getBoosterPack(draft.getNumbersByRarity(), 0, 0, 0); - } - }; // Choose number of boosters final Integer[] integers = new Integer[10]; @@ -298,7 +280,7 @@ public class SealedDeckFormat { Integer nrBoosters = GuiChoose.one("How many booster packs?", integers); for (int i = 0; i < nrBoosters; i++) { - this.product.add(new UnOpenedProduct(fnPick, bpCustom)); + this.product.add(new UnOpenedProduct(draft.getSealedProductTemplate(), draft.getCardPool())); } this.getLandSetCode()[0] = draft.getLandSetCode(); @@ -468,10 +450,12 @@ public class SealedDeckFormat { } final ItemPool pool = new ItemPool(CardPrinted.class); - for (int i = 0; i < this.product.size(); i++) { - pool.addAllFlat(this.product.get(i).open(isHuman, partiality)); + for (UnOpenedProduct prod : product) { + if( prod instanceof UnOpenedMeta ) + pool.addAllFlat(((UnOpenedMeta) prod).open(isHuman, partiality)); + else + pool.addAllFlat(prod.get()); } - return pool; } diff --git a/src/main/java/forge/gui/ImportSourceAnalyzer.java b/src/main/java/forge/gui/ImportSourceAnalyzer.java index 7643a95d6f8..51cb6e018b8 100644 --- a/src/main/java/forge/gui/ImportSourceAnalyzer.java +++ b/src/main/java/forge/gui/ImportSourceAnalyzer.java @@ -380,7 +380,7 @@ public class ImportSourceAnalyzer { _cardFileNamesBySet = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for (CardEdition ce : Singletons.getModel().getEditions()) { Map cardFileNames = new TreeMap(String.CASE_INSENSITIVE_ORDER); - Predicate filter = IPaperCard.Predicates.printedInSets(ce.getCode()); + Predicate filter = IPaperCard.Predicates.printedInSet(ce.getCode()); _addSetCards(cardFileNames, CardDb.instance().getAllCards(), filter); _addSetCards(cardFileNames, CardDb.variants().getAllCards(), filter); _cardFileNamesBySet.put(ce.getCode2(), cardFileNames); diff --git a/src/main/java/forge/gui/InputProxy.java b/src/main/java/forge/gui/InputProxy.java index 5c44c019cfa..723472898e6 100644 --- a/src/main/java/forge/gui/InputProxy.java +++ b/src/main/java/forge/gui/InputProxy.java @@ -43,7 +43,7 @@ public class InputProxy implements Observer { private AtomicReference input = new AtomicReference(); private MatchController match = null; - private static final boolean INPUT_DEBUG = false; + private static final boolean INPUT_DEBUG = true; public void setMatch(MatchController matchController) { match = matchController; diff --git a/src/main/java/forge/gui/match/QuestWinLose.java b/src/main/java/forge/gui/match/QuestWinLose.java index b3b4d2a268d..618d2df5a19 100644 --- a/src/main/java/forge/gui/match/QuestWinLose.java +++ b/src/main/java/forge/gui/match/QuestWinLose.java @@ -32,7 +32,7 @@ import javax.swing.SwingConstants; import forge.Card; import forge.Singletons; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.CardEdition; import forge.card.UnOpenedProduct; import forge.control.FControl; @@ -571,7 +571,7 @@ public class QuestWinLose extends ControlWinLose { } else { final List sets = new ArrayList(); - for (BoosterData bd : Singletons.getModel().getBoosters()) { + for (BoosterTemplate bd : Singletons.getModel().getBoosters()) { if (qData.getFormat().isSetLegal(bd.getEdition())) { sets.add(bd.getEdition()); } @@ -626,7 +626,7 @@ public class QuestWinLose extends ControlWinLose { } final CardEdition chooseEd = GuiChoose.one(setPrompt, chooseEditions); - cardsWon = (new UnOpenedProduct(Singletons.getModel().getBoosters().get(chooseEd.getCode()))).open(); + cardsWon = (new UnOpenedProduct(Singletons.getModel().getBoosters().get(chooseEd.getCode()))).get(); qData.getCards().addAllCards(cardsWon); this.lblTemp1 = new TitleLabel("Bonus " + chooseEd.getName() + " booster pack!"); } diff --git a/src/main/java/forge/item/BoosterPack.java b/src/main/java/forge/item/BoosterPack.java index a195a226c6e..7da9cf1baca 100644 --- a/src/main/java/forge/item/BoosterPack.java +++ b/src/main/java/forge/item/BoosterPack.java @@ -21,7 +21,7 @@ package forge.item; import com.google.common.base.Function; import forge.Singletons; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.CardEdition; import forge.util.MyRandom; @@ -32,12 +32,12 @@ public class BoosterPack extends OpenablePack { public static final Function FN_FROM_SET = new Function() { @Override public BoosterPack apply(final CardEdition arg1) { - BoosterData d = Singletons.getModel().getBoosters().get(arg1.getCode()); + BoosterTemplate d = Singletons.getModel().getBoosters().get(arg1.getCode()); return new BoosterPack(arg1.getName(), d); } }; - public BoosterPack(final String name0, final BoosterData boosterData) { + public BoosterPack(final String name0, final BoosterTemplate boosterData) { super(name0, boosterData); artIndex = MyRandom.getRandom().nextInt(boosterData.getArtIndices()) + 1; hash = super.hashCode() ^ artIndex; @@ -57,7 +57,7 @@ public class BoosterPack extends OpenablePack { return new BoosterPack(name, contents); } - public BoosterData getBoosterData() { + public BoosterTemplate getBoosterData() { return contents; } diff --git a/src/main/java/forge/item/CardDb.java b/src/main/java/forge/item/CardDb.java index e315c2590b5..6faa7e9df36 100644 --- a/src/main/java/forge/item/CardDb.java +++ b/src/main/java/forge/item/CardDb.java @@ -249,7 +249,6 @@ public final class CardDb { if (null == result) { throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name)); } - } } if (isFoil) { diff --git a/src/main/java/forge/item/FatPack.java b/src/main/java/forge/item/FatPack.java index 058e5a4742f..ff61c13c3ed 100644 --- a/src/main/java/forge/item/FatPack.java +++ b/src/main/java/forge/item/FatPack.java @@ -24,21 +24,22 @@ import java.util.List; import com.google.common.base.Function; import forge.Singletons; +import forge.card.BoosterGenerator; import forge.card.CardEdition; -import forge.card.FatPackData; +import forge.card.FatPackTemplate; public class FatPack extends OpenablePack { public static final Function FN_FROM_SET = new Function() { @Override public FatPack apply(final CardEdition arg1) { - FatPackData d = Singletons.getModel().getFatPacks().get(arg1.getCode()); + FatPackTemplate d = Singletons.getModel().getFatPacks().get(arg1.getCode()); return new FatPack(arg1.getName(), d); } }; - private final FatPackData fpData; + private final FatPackTemplate fpData; - public FatPack(final String name0, final FatPackData fpData0) { + public FatPack(final String name0, final FatPackTemplate fpData0) { super(name0, Singletons.getModel().getBoosters().get(fpData0.getEdition())); fpData = fpData0; } @@ -59,7 +60,7 @@ public class FatPack extends OpenablePack { for (int i = 0; i < fpData.getCntBoosters(); i++) { result.addAll(super.generate()); } - result.addAll(getRandomBasicLands(fpData.getLandEdition(), fpData.getCntLands())); + result.addAll(BoosterGenerator.getBoosterPack(contents)); return result; } @@ -70,6 +71,6 @@ public class FatPack extends OpenablePack { @Override public int getTotalCards() { - return super.getTotalCards() * fpData.getCntBoosters() + fpData.getCntLands(); + return super.getTotalCards() * fpData.getCntBoosters() + fpData.getTotal(); } } diff --git a/src/main/java/forge/item/IPaperCard.java b/src/main/java/forge/item/IPaperCard.java index d7d462e847f..04e75ce6e58 100644 --- a/src/main/java/forge/item/IPaperCard.java +++ b/src/main/java/forge/item/IPaperCard.java @@ -1,6 +1,5 @@ package forge.item; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -8,6 +7,7 @@ import java.util.Set; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Predicate; +import com.google.common.collect.Lists; import forge.Card; import forge.card.CardRarity; @@ -25,6 +25,9 @@ public interface IPaperCard extends InventoryItem { public static Predicate rarity(final boolean isEqual, final CardRarity value) { return new PredicateRarity(value, isEqual); } + public static Predicate printedInSets(final String[] sets) { + return printedInSets(Lists.newArrayList(sets), true); + } public static Predicate printedInSets(final List value, final boolean shouldContain) { if ((value == null) || value.isEmpty()) { @@ -33,11 +36,11 @@ public interface IPaperCard extends InventoryItem { return new PredicateSets(value, shouldContain); } - public static Predicate printedInSets(final String value) { + public static Predicate printedInSet(final String value) { if (StringUtils.isEmpty(value)) { return com.google.common.base.Predicates.alwaysTrue(); } - return new PredicateSets(Arrays.asList(new String[] { value }), true); + return new PredicateSets(Lists.newArrayList(value), true); } public static Predicate name(final String what) { @@ -48,8 +51,8 @@ public interface IPaperCard extends InventoryItem { return new PredicateName(op, what); } - public static Predicate namesExcept(final List what) { - return new PredicateNamesExcept(what); + public static Predicate names(final List what) { + return new PredicateNames(what); } private static class PredicateRarity implements Predicate { @@ -96,7 +99,7 @@ public interface IPaperCard extends InventoryItem { } } - private static class PredicateNamesExcept extends PredicateString { + private static class PredicateNames extends PredicateString { private final List operand; @Override @@ -104,13 +107,13 @@ public interface IPaperCard extends InventoryItem { final String cardName = card.getName(); for (final String element : this.operand) { if (this.op(cardName, element)) { - return false; + return true; } } - return true; + return false; } - public PredicateNamesExcept(final List operand) { + public PredicateNames(final List operand) { super(StringOp.EQUALS); this.operand = operand; } @@ -143,7 +146,7 @@ public interface IPaperCard extends InventoryItem { public static final Predicate IS_SPECIAL = Predicates.rarity(true, CardRarity.Special); /** The Constant exceptLands. */ - public static final Predicate EXCEPT_LANDS = Predicates.rarity(false, CardRarity.BasicLand); + public static final Predicate IS_BASIC_LAND = Predicates.rarity(true, CardRarity.BasicLand); } } diff --git a/src/main/java/forge/item/OpenablePack.java b/src/main/java/forge/item/OpenablePack.java index b7619d0a320..e8678f1c494 100644 --- a/src/main/java/forge/item/OpenablePack.java +++ b/src/main/java/forge/item/OpenablePack.java @@ -26,19 +26,18 @@ import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.BoosterGenerator; import forge.card.CardRulesPredicates; import forge.util.Aggregates; public abstract class OpenablePack implements InventoryItemFromSet { - protected final BoosterData contents; + protected final BoosterTemplate contents; protected final String name; private final int hash; private List cards = null; - private BoosterGenerator generator = null; - public OpenablePack(String name0, BoosterData boosterData) { + public OpenablePack(String name0, BoosterTemplate boosterData) { if (null == name0) { throw new NullArgumentException("name0"); } if (null == boosterData) { throw new NullArgumentException("boosterData"); } contents = boosterData; @@ -93,16 +92,7 @@ public abstract class OpenablePack implements InventoryItemFromSet { } protected List generate() { - if (null == generator) { - generator = new BoosterGenerator(contents.getEditionFilter()); - } - final List myCards = generator.getBoosterPack(contents); - - final int cntLands = contents.getCntLands(); - if (cntLands > 0) { - myCards.add(getRandomBasicLand(contents.getLandEdition())); - } - return myCards; + return BoosterGenerator.getBoosterPack(contents); } protected CardPrinted getRandomBasicLand(final String setCode) { @@ -111,7 +101,7 @@ public abstract class OpenablePack implements InventoryItemFromSet { protected List getRandomBasicLands(final String setCode, final int count) { Predicate cardsRule = Predicates.and( - IPaperCard.Predicates.printedInSets(setCode), + IPaperCard.Predicates.printedInSet(setCode), Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, CardPrinted.FN_GET_RULES)); return Aggregates.random(Iterables.filter(CardDb.instance().getAllCards(), cardsRule), count); } diff --git a/src/main/java/forge/item/PrintSheet.java b/src/main/java/forge/item/PrintSheet.java new file mode 100644 index 00000000000..36abe27081e --- /dev/null +++ b/src/main/java/forge/item/PrintSheet.java @@ -0,0 +1,71 @@ +package forge.item; + +import java.util.List; +import java.util.Map.Entry; +import java.util.ArrayList; +import java.util.Collection; +import forge.util.MyRandom; + + +/** + * TODO: Write javadoc for this type. + * + */ +public class PrintSheet { + private final ItemPool cardsWithWeights = new ItemPool(CardPrinted.class); + + + public void add(CardPrinted card) { + add(card,1); + } + + public void add(CardPrinted card, int weight) { + cardsWithWeights.add(card, weight); + } + + public void addAll(Iterable cards) { + addAll(cards, 1); + } + + public void addAll(Iterable cards, int weight) { + for(CardPrinted card : cards) + cardsWithWeights.add(card, weight); + } + + private CardPrinted fetchRoulette(int start, int roulette, Collection toSkip) { + int sum = start; + boolean isSecondRun = start > 0; + for(Entry cc : cardsWithWeights ) { + sum += cc.getValue().intValue(); + if( sum > roulette ) { + if( toSkip != null && toSkip.contains(cc.getKey())) + continue; + return cc.getKey(); + } + } + if( isSecondRun ) + throw new IllegalStateException("Print sheet does not have enough unique cards"); + + return fetchRoulette(sum + 1, roulette, toSkip); // start over from beginning, in case last cards were to skip + } + + public CardPrinted random() { + int totalWeight = cardsWithWeights.countAll(); + int index = MyRandom.getRandom().nextInt(totalWeight); + return fetchRoulette(0, index, null); + } + + public List random(int number, boolean wantUnique) { + List result = new ArrayList(); + + int totalWeight = cardsWithWeights.countAll(); + for(int iC = 0; iC < number; iC++) { + int index = MyRandom.getRandom().nextInt(totalWeight); + CardPrinted toAdd = fetchRoulette(0, index, wantUnique ? result : null); + result.add(toAdd); + } + return result; + } + + +} diff --git a/src/main/java/forge/item/TournamentPack.java b/src/main/java/forge/item/TournamentPack.java index 1865ea35619..bddb6412e95 100644 --- a/src/main/java/forge/item/TournamentPack.java +++ b/src/main/java/forge/item/TournamentPack.java @@ -22,7 +22,7 @@ import java.util.List; import com.google.common.base.Function; import forge.Singletons; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.BoosterGenerator; import forge.card.CardEdition; @@ -32,17 +32,17 @@ public class TournamentPack extends OpenablePack { public static final Function FN_FROM_SET = new Function() { @Override public TournamentPack apply(final CardEdition arg1) { - BoosterData d = Singletons.getModel().getTournamentPacks().get(arg1.getCode()); + BoosterTemplate d = Singletons.getModel().getTournamentPacks().get(arg1.getCode()); return new TournamentPack(arg1.getName(), d); } }; - public TournamentPack(final String name0, final BoosterData boosterData) { + public TournamentPack(final String name0, final BoosterTemplate boosterData) { super(name0, boosterData); } public final boolean isStarterDeck() { - return contents.getCommon() < 30; + return contents.getSlots().get(0).getRight() < 30; // hack - getting number of commons, they are first in list } @Override @@ -52,8 +52,7 @@ public class TournamentPack extends OpenablePack { @Override protected List generate() { - final BoosterGenerator gen = new BoosterGenerator(this.contents.getEditionFilter()); - return gen.getBoosterPack(this.contents); + return BoosterGenerator.getBoosterPack(this.contents); } @Override diff --git a/src/main/java/forge/model/FModel.java b/src/main/java/forge/model/FModel.java index 3a29a237156..7a6e1ae4ebd 100644 --- a/src/main/java/forge/model/FModel.java +++ b/src/main/java/forge/model/FModel.java @@ -28,11 +28,11 @@ import java.util.List; import forge.Constant; import forge.Constant.Preferences; import forge.FThreads; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.CardBlock; import forge.card.CardRulesReader; import forge.card.EditionCollection; -import forge.card.FatPackData; +import forge.card.FatPackTemplate; import forge.card.FormatCollection; import forge.card.cardfactory.CardStorageReader; import forge.deck.CardCollections; @@ -83,9 +83,9 @@ public enum FModel { private final EditionCollection editions; private final FormatCollection formats; - private final IStorageView boosters; - private final IStorageView tournaments; - private final IStorageView fatPacks; + private final IStorageView boosters; + private final IStorageView tournaments; + private final IStorageView fatPacks; private final IStorageView blocks; private final IStorageView fantasyBlocks; private final IStorageView worlds; @@ -144,9 +144,9 @@ public enum FModel { this.editions = CardRulesReader.editions; // CardRules ctor cannot refer to FModel, since it is not yet build by that moment this.formats = new FormatCollection("res/blockdata/formats.txt"); - this.boosters = new StorageView(new BoosterData.Reader("res/blockdata/boosters.txt")); - this.tournaments = new StorageView(new BoosterData.Reader("res/blockdata/starters.txt")); - this.fatPacks = new StorageView(new FatPackData.Reader("res/blockdata/fatpacks.txt")); + this.boosters = new StorageView(new BoosterTemplate.Reader("res/blockdata/boosters.txt")); + this.tournaments = new StorageView(new BoosterTemplate.Reader("res/blockdata/starters.txt")); + this.fatPacks = new StorageView(new FatPackTemplate.Reader("res/blockdata/fatpacks.txt")); this.blocks = new StorageView(new CardBlock.Reader("res/blockdata/blocks.txt", editions)); this.fantasyBlocks = new StorageView(new CardBlock.Reader("res/blockdata/fantasyblocks.txt", editions)); this.worlds = new StorageView(new QuestWorld.Reader("res/quest/world/worlds.txt")); @@ -358,18 +358,18 @@ public enum FModel { return fantasyBlocks; } - /** @return {@link forge.util.storage.IStorageView}<{@link forge.card.FatPackData}> */ - public IStorageView getFatPacks() { + /** @return {@link forge.util.storage.IStorageView}<{@link forge.card.FatPackTemplate}> */ + public IStorageView getFatPacks() { return fatPacks; } - /** @return {@link forge.util.storage.IStorageView}<{@link forge.card.BoosterData}> */ - public final IStorageView getTournamentPacks() { + /** @return {@link forge.util.storage.IStorageView}<{@link forge.card.BoosterTemplate}> */ + public final IStorageView getTournamentPacks() { return tournaments; } - /** @return {@link forge.util.storage.IStorageView}<{@link forge.card.BoosterData}> */ - public final IStorageView getBoosters() { + /** @return {@link forge.util.storage.IStorageView}<{@link forge.card.BoosterTemplate}> */ + public final IStorageView getBoosters() { return boosters; } diff --git a/src/main/java/forge/quest/BoosterUtils.java b/src/main/java/forge/quest/BoosterUtils.java index 6785457eda9..d382dc7fdc7 100644 --- a/src/main/java/forge/quest/BoosterUtils.java +++ b/src/main/java/forge/quest/BoosterUtils.java @@ -23,16 +23,15 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; -import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.Singletons; -import forge.card.BoosterGenerator; import forge.card.CardRules; import forge.card.CardRulesPredicates; +import forge.card.SealedProductTemplate; import forge.card.UnOpenedProduct; import forge.item.BoosterPack; import forge.item.CardDb; @@ -228,9 +227,9 @@ public final class BoosterUtils { * */ public static Predicate parseRulesLimitation(final String input) { - if (null == input) { - return null; - } + if (null == input) + return Predicates.alwaysTrue(); + if (input.equalsIgnoreCase("black")) { return CardRulesPredicates.Presets.IS_BLACK; } else if (input.equalsIgnoreCase("blue")) { @@ -260,8 +259,8 @@ public final class BoosterUtils { } else if (input.equalsIgnoreCase("enchantment")) { return CardRulesPredicates.Presets.IS_ENCHANTMENT; } - // No CardRules limitations could be parsed - return null; + + throw new IllegalArgumentException("No CardRules limitations could be parsed from: " + input); } /** * parseReward - used internally to parse individual items in a challenge reward definition. @@ -282,25 +281,16 @@ public final class BoosterUtils { final Predicate rar = IPaperCard.Predicates.Presets.IS_RARE_OR_MYTHIC; // Determine color ("random" defaults to null color) - Predicate col = Predicates.alwaysTrue(); - final Predicate colorRules = parseRulesLimitation(temp[1]); + Predicate col = parseRulesLimitation(temp[1]); - if (colorRules != null) { - col = colorRules; - } - - Function> openWay = new Function>() { - @Override - public List apply(BoosterGenerator arg1) { - return arg1.getSingletonBoosterPack(qty); - } - }; Predicate colorPred = Predicates.compose(col, CardPrinted.FN_GET_RULES); Predicate rarAndColor = Predicates.and(rar, colorPred); if (Singletons.getModel().getQuest().getFormat() != null) { rarAndColor = Predicates.and(Singletons.getModel().getQuest().getFormat().getFilterPrinted(), rarAndColor); } - rewards.addAll(new UnOpenedProduct(openWay, new BoosterGenerator(rarAndColor)).open()); + Iterable cardPool = Iterables.filter(CardDb.instance().getAllCards(), rarAndColor); + UnOpenedProduct product = new UnOpenedProduct(new SealedProductTemplate(qty), cardPool); + rewards.addAll(product.get()); } else if (temp.length == 2 && temp[0].equalsIgnoreCase("duplicate") && temp[1].equalsIgnoreCase("card")) { // Type 2: a duplicate card of the players choice rewards.add(new QuestRewardCardDuplicate()); diff --git a/src/main/java/forge/quest/QuestUtilCards.java b/src/main/java/forge/quest/QuestUtilCards.java index c648bd57009..d3091d4d906 100644 --- a/src/main/java/forge/quest/QuestUtilCards.java +++ b/src/main/java/forge/quest/QuestUtilCards.java @@ -21,16 +21,20 @@ import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; +import org.apache.commons.lang3.tuple.Pair; + import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import forge.Singletons; import forge.card.BoosterGenerator; import forge.card.CardEdition; import forge.card.CardRarity; import forge.card.FormatCollection; +import forge.card.SealedProductTemplate; import forge.deck.Deck; import forge.deck.DeckSection; import forge.item.BoosterPack; @@ -521,8 +525,6 @@ public final class QuestUtilCards { qc.getFormat().getFilterPrinted()); } - final BoosterGenerator pack = new BoosterGenerator(cardList); - int nLevel = this.qc.getAchievements().getLevel(); // Preferences @@ -537,8 +539,13 @@ public final class QuestUtilCards { final int winPacks = this.qc.getAchievements().getWin() / winsForPack; final int totalPacks = Math.min(levelPacks + winPacks, maxPacks); + @SuppressWarnings("unchecked") + SealedProductTemplate template = new SealedProductTemplate(Lists.newArrayList( + Pair.of("Commmon", common), Pair.of("uncommmon", uncommon), Pair.of("Rare", rare) + )); + for (int i = 0; i < totalPacks; i++) { - this.qa.getShopList().addAllFlat(pack.getBoosterPack(common, uncommon, rare, 0, 0, 0, 0, 0, 0)); + this.qa.getShopList().addAllFlat(BoosterGenerator.getBoosterPack(template, cardList)); } this.generateBoostersInShop(totalPacks); @@ -631,7 +638,7 @@ public final class QuestUtilCards { public int getCompletionPercent(String edition) { // get all cards in the specified edition - Predicate filter = IPaperCard.Predicates.printedInSets(edition); + Predicate filter = IPaperCard.Predicates.printedInSet(edition); Iterable editionCards = Iterables.filter(CardDb.instance().getAllCards(), filter); ItemPool ownedCards = qa.getCardPool(); diff --git a/src/main/java/forge/quest/QuestUtilUnlockSets.java b/src/main/java/forge/quest/QuestUtilUnlockSets.java index d4472ea2b2b..2c3b221a4cd 100644 --- a/src/main/java/forge/quest/QuestUtilUnlockSets.java +++ b/src/main/java/forge/quest/QuestUtilUnlockSets.java @@ -31,7 +31,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.Singletons; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.CardEdition; import forge.card.UnOpenedProduct; import forge.gui.CardListViewer; @@ -184,21 +184,21 @@ public class QuestUtilUnlockSets { */ public static void doUnlock(QuestController qData, final CardEdition unlockedSet) { - IStorageView starters = Singletons.getModel().getTournamentPacks(); - IStorageView boosters = Singletons.getModel().getBoosters(); + IStorageView starters = Singletons.getModel().getTournamentPacks(); + IStorageView boosters = Singletons.getModel().getBoosters(); qData.getFormat().unlockSet(unlockedSet.getCode()); List cardsWon = new ArrayList(); if (starters.contains(unlockedSet.getCode())) { UnOpenedProduct starter = new UnOpenedProduct(starters.get(unlockedSet.getCode())); - cardsWon.addAll(starter.open()); + cardsWon.addAll(starter.get()); } else if (boosters.contains(unlockedSet.getCode())) { UnOpenedProduct booster = new UnOpenedProduct(boosters.get(unlockedSet.getCode())); - cardsWon.addAll(booster.open()); - cardsWon.addAll(booster.open()); - cardsWon.addAll(booster.open()); + cardsWon.addAll(booster.get()); + cardsWon.addAll(booster.get()); + cardsWon.addAll(booster.get()); } qData.getCards().addAllCards(cardsWon); diff --git a/src/main/java/forge/util/TextUtil.java b/src/main/java/forge/util/TextUtil.java index a85abcab2c7..c61be125787 100644 --- a/src/main/java/forge/util/TextUtil.java +++ b/src/main/java/forge/util/TextUtil.java @@ -52,7 +52,11 @@ public class TextUtil { public static String[] splitWithParenthesis(CharSequence input, char delimiter, char openPar, char closePar) { return splitWithParenthesis(input, delimiter, Integer.MAX_VALUE, openPar, closePar, true); } - + + public static String[] splitWithParenthesis(CharSequence input, char delimiter, char openPar, char closePar, int limit) { + return splitWithParenthesis(input, delimiter, limit, openPar, closePar, true); + } + /** * Split string separated by a single char delimiter, can take parenthesis in account * It's faster than String.split, and allows parenthesis diff --git a/src/test/java/forge/BoosterDraftTest.java b/src/test/java/forge/BoosterDraftTest.java index a9edfb28347..5f20d45ed39 100644 --- a/src/test/java/forge/BoosterDraftTest.java +++ b/src/test/java/forge/BoosterDraftTest.java @@ -4,7 +4,7 @@ import java.util.List; import org.testng.annotations.Test; -import forge.card.BoosterData; +import forge.card.BoosterTemplate; import forge.card.BoosterGenerator; import forge.deck.Deck; import forge.game.limited.IBoosterDraft; @@ -49,9 +49,8 @@ public class BoosterDraftTest implements IBoosterDraft { @Override public ItemPoolView nextChoice() { this.n--; - BoosterData booster = Singletons.getModel().getBoosters().get("M11"); - final BoosterGenerator pack = new BoosterGenerator(booster.getEditionFilter()); - return ItemPool.createFrom(pack.getBoosterPack(booster), CardPrinted.class); + BoosterTemplate booster = Singletons.getModel().getBoosters().get("M11"); + return ItemPool.createFrom(BoosterGenerator.getBoosterPack(booster), CardPrinted.class); } /** {@inheritDoc} */