aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rwxr-xr-xcardbase.py36
-rwxr-xr-xfulltest.sh2
-rwxr-xr-xtest_callow.py18
-rwxr-xr-xtest_island.py74
-rwxr-xr-xtest_shivandragon.py2
-rwxr-xr-xtest_shoal.py75
-rwxr-xr-xtest_sorin.py18
-rw-r--r--testcards/callow (renamed from callow)0
-rw-r--r--testcards/coecon (renamed from coecon)0
-rw-r--r--testcards/island (renamed from island)0
-rw-r--r--testcards/shivandragon (renamed from shivandragon)0
-rw-r--r--testcards/shoal (renamed from shoal)0
-rw-r--r--testcards/sorin (renamed from sorin)0
-rw-r--r--testcards/ugincons389
15 files changed, 600 insertions, 17 deletions
diff --git a/.travis.yml b/.travis.yml
index c75f59f..c2a5f06 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,4 +4,5 @@ python:
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install: pip install lxml requests
# command to run tests, e.g. python setup.py test
-script: python -m unittest test_shivandragon test_callow test_cardclass test_sorin
+#script: python -m unittest test_shivandragon test_callow test_cardclass test_sorin
+script: fulltest.sh
diff --git a/cardbase.py b/cardbase.py
index 142c5a5..b6942ee 100755
--- a/cardbase.py
+++ b/cardbase.py
@@ -39,20 +39,29 @@ def extractSubTitle(page):
def getCost(page):
cost = extractSubTitle(page)
+ cost = re.search(" ([0-9X]*[WGRBU]*) ", cost)
- return re.search(" ([0-9X]*[WGRBU]*) ", cost).group(1)
+ if cost:
+ return cost.group(1)
+ else:
+ return ""
def getColour(page):
colours = extractSubTitle(page)
- colours = re.search(" [0-9X]*([WGRBU]*) ", colours).group(1)
-
- colours = re.sub("U+", "U", colours)
- colours = re.sub("W+", "W", colours)
- colours = re.sub("R+", "R", colours)
- colours = re.sub("B+", "B", colours)
- colours = re.sub("G+", "G", colours)
-
- return colours
+ colours = re.search(" [0-9X]*([WGRBU]*) ", colours)
+ if colours:
+ colours = colours.group(1)
+
+ colours = re.sub("U+", "U", colours)
+ colours = re.sub("W+", "W", colours)
+ colours = re.sub("R+", "R", colours)
+ colours = re.sub("B+", "B", colours)
+ colours = re.sub("G+", "G", colours)
+
+ return colours
+
+ else:
+ return ""
def getType(page):
types = extractSubTitle(page)
@@ -62,9 +71,12 @@ def getType(page):
def getSubType(page):
subtypes = extractSubTitle(page)
- subtypes = re.search("— ([A-Za-z ]*) ", subtypes).group(1)
+ subtypes = re.search("— ([A-Za-z ]*)", subtypes)
- return subtypes
+ if subtypes:
+ return subtypes.group(1).strip()
+ else:
+ return ""
def getArtist(page):
artist = page.xpath("/html/body/table[3]/tr/td[2]/p[4]/text()")[0]
diff --git a/fulltest.sh b/fulltest.sh
index 202eb5e..03891b4 100755
--- a/fulltest.sh
+++ b/fulltest.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env zsh
-python -m unittest test_shivandragon test_callow test_cardclass test_sorin
+python -m unittest test_shivandragon test_callow test_cardclass test_sorin test_island test_shoal
diff --git a/test_callow.py b/test_callow.py
index 72d25ff..452029c 100755
--- a/test_callow.py
+++ b/test_callow.py
@@ -9,7 +9,7 @@ class Test_cardInformationParsing(unittest.TestCase):
@classmethod
def setUpClass(cls):
- with open("callow", "r") as file:
+ with open("testcards/callow", "r") as file:
cls.page = html.fromstring(file.read())
# Tests
@@ -49,6 +49,22 @@ class Test_cardInformationParsing(unittest.TestCase):
def test_correctLoyaltyIsParsed(self):
self.assertEqual(cardbase.getLoyalty(self.page), "")
+class Test_additionalCardData(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.card = cardbase.fetchCard("bok", "31a")
+
+ def test_cardHasCorrectEdition(self):
+ self.assertEqual(self.card.edition, "bok")
+
+ def test_cardHasCorrectScan(self):
+ self.assertEqual(self.card.scan, "http://magiccards.info/scans/en/bok/31a.jpg")
+
+ def test_cardHasCorrectNumber(self):
+ self.assertEqual(self.card.number, "31a")
+
+
def test():
unittest.main(exit=False)
diff --git a/test_island.py b/test_island.py
new file mode 100755
index 0000000..44641cb
--- /dev/null
+++ b/test_island.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+
+import sys
+import unittest
+import cardbase
+from lxml import html
+
+
+class Test_cardInformationParsing(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ # but actually, use the pre-fetched file to avoid querying the server too much
+ with open("testcards/island", "r") as file:
+ cls.page = html.fromstring(file.read())
+
+ # Tests
+ def test_correctTitleIsParsed(self):
+ self.assertEqual(cardbase.getTitle(self.page), "Island")
+
+ def test_correctCostIsParsed(self):
+ self.assertEqual(cardbase.getCost(self.page), "")
+
+ def test_correctColourIsParsed(self):
+ self.assertEqual(cardbase.getColour(self.page), "")
+
+ def test_correctTypeIsParsed(self):
+ self.assertEqual(cardbase.getType(self.page), "Basic Land")
+
+ def test_correctSubTypeIsParsed(self):
+ self.assertEqual(cardbase.getSubType(self.page), "Island")
+
+ def test_correctArtistIsParsed(self):
+ self.assertEqual(cardbase.getArtist(self.page), "Florian de Gesincourt")
+
+ def test_correctTextIsParsed(self):
+ self.assertEqual(cardbase.getText(self.page), ["({T}: Add {U} to your mana pool.)"])
+
+ def test_correctFlavourIsParsed(self):
+ self.assertEqual(cardbase.getFlavour(self.page), "")
+
+ def test_correctRarityIsParsed(self):
+ self.assertEqual(cardbase.getRarity(self.page), "Land")
+
+ def test_correctPowerIsParsed(self):
+ self.assertEqual(cardbase.getPower(self.page), "")
+
+ def test_correctToughnessIsParsed(self):
+ self.assertEqual(cardbase.getToughness(self.page), "")
+
+ def test_correctLoyaltyIsParsed(self):
+ self.assertEqual(cardbase.getLoyalty(self.page), "")
+
+class Test_additionalCardData(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.card = cardbase.fetchCard("dtk", "253")
+
+ def test_cardHasCorrectEdition(self):
+ self.assertEqual(self.card.edition, "dtk")
+
+ def test_cardHasCorrectScan(self):
+ self.assertEqual(self.card.scan, "http://magiccards.info/scans/en/dtk/253.jpg")
+
+ def test_cardHasCorrectNumber(self):
+ self.assertEqual(self.card.number, "253")
+
+def test():
+ unittest.main(exit=False)
+
+# The entry point
+if __name__ == "__main__":
+ test()
diff --git a/test_shivandragon.py b/test_shivandragon.py
index e802251..4f003e6 100755
--- a/test_shivandragon.py
+++ b/test_shivandragon.py
@@ -14,7 +14,7 @@ class Test_cardInformationParsing(unittest.TestCase):
# cls.page = html.fromstring(requests.get("http://magiccards.info/m15/en/281.html").text)
# but actually, use the pre-fetched file to avoid querying the server too much
- with open("shivandragon", "r") as file:
+ with open("testcards/shivandragon", "r") as file:
cls.page = html.fromstring(file.read())
# Tests
diff --git a/test_shoal.py b/test_shoal.py
new file mode 100755
index 0000000..610ce4b
--- /dev/null
+++ b/test_shoal.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+
+import sys
+import unittest
+import cardbase
+from lxml import html
+
+
+class Test_cardInformationParsing(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ # but actually, use the pre-fetched file to avoid querying the server too much
+ with open("testcards/shoal", "r") as file:
+ cls.page = html.fromstring(file.read())
+
+ # Tests
+ def test_correctTitleIsParsed(self):
+ self.assertEqual(cardbase.getTitle(self.page), "Disrupting Shoal")
+
+ def test_correctCostIsParsed(self):
+ self.assertEqual(cardbase.getCost(self.page), "XUU")
+
+ def test_correctColourIsParsed(self):
+ self.assertEqual(cardbase.getColour(self.page), "U")
+
+ def test_correctTypeIsParsed(self):
+ self.assertEqual(cardbase.getType(self.page), "Instant")
+
+ def test_correctSubTypeIsParsed(self):
+ self.assertEqual(cardbase.getSubType(self.page), "Arcane")
+
+ def test_correctArtistIsParsed(self):
+ self.assertEqual(cardbase.getArtist(self.page), "Scott M. Fischer")
+
+ def test_correctTextIsParsed(self):
+ self.assertEqual(cardbase.getText(self.page), ["You may exile a blue card with converted mana cost X from your hand rather than pay Disrupting Shoal's mana cost.", "Counter target spell if its converted mana cost is X."])
+
+ def test_correctFlavourIsParsed(self):
+ self.assertEqual(cardbase.getFlavour(self.page), "")
+
+ def test_correctRarityIsParsed(self):
+ self.assertEqual(cardbase.getRarity(self.page), "Rare")
+
+ def test_correctPowerIsParsed(self):
+ self.assertEqual(cardbase.getPower(self.page), "")
+
+ def test_correctToughnessIsParsed(self):
+ self.assertEqual(cardbase.getToughness(self.page), "")
+
+ def test_correctLoyaltyIsParsed(self):
+ self.assertEqual(cardbase.getLoyalty(self.page), "")
+
+class Test_additionalCardData(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.card = cardbase.fetchCard("bok", "33")
+
+ def test_cardHasCorrectEdition(self):
+ self.assertEqual(self.card.edition, "bok")
+
+ def test_cardHasCorrectScan(self):
+ self.assertEqual(self.card.scan, "http://magiccards.info/scans/en/bok/33.jpg")
+
+ def test_cardHasCorrectNumber(self):
+ self.assertEqual(self.card.number, "33")
+
+
+def test():
+ unittest.main(exit=False)
+
+# The entry point
+if __name__ == "__main__":
+ test()
diff --git a/test_sorin.py b/test_sorin.py
index 5ae732b..05192f8 100755
--- a/test_sorin.py
+++ b/test_sorin.py
@@ -10,7 +10,7 @@ class Test_cardInformationParsing(unittest.TestCase):
@classmethod
def setUpClass(cls):
- with open("sorin", "r") as file:
+ with open("testcards/sorin", "r") as file:
cls.page = html.fromstring(file.read())
# Tests
@@ -50,6 +50,22 @@ class Test_cardInformationParsing(unittest.TestCase):
def test_correctLoyaltyIsParsed(self):
self.assertEqual(cardbase.getLoyalty(self.page), "4")
+class Test_additionalCardData(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.card = cardbase.fetchCard("m12", "109")
+
+ def test_cardHasCorrectEdition(self):
+ self.assertEqual(self.card.edition, "m12")
+
+ def test_cardHasCorrectScan(self):
+ self.assertEqual(self.card.scan, "http://magiccards.info/scans/en/m12/109.jpg")
+
+ def test_cardHasCorrectNumber(self):
+ self.assertEqual(self.card.number, "109")
+
+
def test():
unittest.main(exit=False)
diff --git a/callow b/testcards/callow
index fde0e5c..fde0e5c 100644
--- a/callow
+++ b/testcards/callow
diff --git a/coecon b/testcards/coecon
index bcdf681..bcdf681 100644
--- a/coecon
+++ b/testcards/coecon
diff --git a/island b/testcards/island
index 40b6677..40b6677 100644
--- a/island
+++ b/testcards/island
diff --git a/shivandragon b/testcards/shivandragon
index 9ba92c1..9ba92c1 100644
--- a/shivandragon
+++ b/testcards/shivandragon
diff --git a/shoal b/testcards/shoal
index 43aa6af..43aa6af 100644
--- a/shoal
+++ b/testcards/shoal
diff --git a/sorin b/testcards/sorin
index 1042a46..1042a46 100644
--- a/sorin
+++ b/testcards/sorin
diff --git a/testcards/ugincons b/testcards/ugincons
new file mode 100644
index 0000000..150ea02
--- /dev/null
+++ b/testcards/ugincons
@@ -0,0 +1,389 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <title>Ugin's Construct (Fate Reforged)</title>
+ <style type="text/css">
+ <!--
+ body {background: #fafafa url(http://magiccards.info/images/bg.gif) repeat-x;margin: 1em 1.5em;}
+ body,td,th {font: 0.9em/1.2em Verdana;color: #444;}
+ th {text-align: left; font-weight: bold;}
+ p {margin: 0.5em 0;}
+ a {color: #4666BC;}
+ a:hover {color: #333;background-color: #ff0;}
+ a:active {text-decoration: none;}
+ a:visited {color: #283C71;}
+ li.legal {color: #216728;}
+ li.restricted {color: #B98420;}
+ li.banned {color: #672121;}
+ li.reserve {color: #4F55CC;}
+ p.ctext {background-color: #fff;padding: 4px;}
+ p.otext {background-color: #fff;padding: 4px;}
+ div.oo {margin-left: 0em; padding: 0.5em 0 0 0; border: 1px solid #bbb; font-size: 75%;line-height: 100%;}
+ div.oo span {padding: 4px;}
+ div.oo p {margin: 0.5em 0 0 0;}
+ tr.odd {background-color: #e0e0e0;}
+ tr.even {background-color: #fafafa;}
+ #searchhelper td {line-height: 150%;vertical-align: middle;border-bottom: 1px dotted #999; padding: 5px 5px 5px 0;}
+ #searchhelper label {font-weight: bold;}
+ #searchhelper label.sl {font-weight: normal;}
+ #searchhelper table td {border: none; padding: 0; font-size: 1em;}
+ span.missing {color: #aaa;font-weight:bold;font-style:italic;}
+ dt {font-weight: bold; font-size: 110%; margin: 1em 0 0.5em 0;}
+ table#nav {font-size: 90%;}
+ ul {padding-left: 2em;}
+ .flag {vertical-align:-10%;}
+ .flag2 {vertical-align:-20%;}
+ .addition {color: red;}
+ a.ruleanchor {text-decoration: none; color: #E8DA58;}
+ li:target {background: #FAF7DC;}
+ -->
+ </style>
+ <script type="text/javascript">
+ <!--
+ function preventFocus() { isTop = false; }
+ function focusForm() { if (isTop && document.f) { document.f.q.select(); } }
+ var isTop = true;
+ window.onscroll = preventFocus;
+ window.onload = focusForm;
+ // -->
+ </script>
+ <link rel="search" type="application/opensearchdescription+xml" title="MagicCards.Info" href="/opensearch.xml">
+</head>
+<body>
+<table width="100%" cellpadding="0" cellspacing="0" id="nav">
+ <tr>
+ <td>
+ <img src="http://magiccards.info/images/en.gif" alt="English" width="16" height="11" class="flag2">
+ <a href="/">Home</a>,
+ <a href="/random.html">Random</a>,
+ <a href="/art.html">Art Game</a>,
+ <a href="/search.html"><b>Advanced</b></a>,
+ <a href="/extras.html">Extras</a>,
+ <a href="/rules.html">Rules</a>,
+ <a href="/about.html">About</a>.
+ </td>
+ <td align="right">
+ Sets:
+ <a href="/dtk/en.html">Dragons of Tarkir</a>, <a href="/frf/en.html">Fate Reforged</a>, <a href="/m15/en.html">Magic 2015</a>, <a href="/cns/en.html">Conspiracy</a>
+ &gt; <a href="/sitemap.html"><b>All Sets</b></a>
+ </td>
+ </tr>
+</table>
+<hr>
+<form method="GET" action="/query" style="font-size: 1.5em;" name="f">
+<table border="0" cellpadding="0" cellspacing="0" width="100%" align="center">
+ <tr>
+ <td nowrap="nowrap">
+ <label for="q">Query:</label>
+ <input type="text" name="q" id="q" size="30" value="" style="font-size: 1em;" tabindex="1">
+
+ </td>
+ <td align="right">
+ <select name="v" onchange="this.form.submit();">
+ <optgroup label="Select Output Format:">
+
+ <option value="card" selected="selected">View as Cards with Scans</option>
+ <option value="olist">View as a List (Oracle)</option>
+ <option value="list">View as Checklist</option>
+ <option value="scan">View as Scans only</option>
+ <option value="spoiler">View as a Spoiler</option>
+ </optgroup>
+ </select>
+ <select name="s" onchange="this.form.submit();">
+ <optgroup label="Select Sort Order:">
+
+ <option value="cname" selected="selected">Sort by Name &gt; Edition</option>
+ <option value="color">Sort by Color &gt; Name</option>
+ <option value="otype">Sort by Type &gt; Name</option>
+ <option value="cmc">Sort by Converted Mana Cost &gt; Name</option>
+ <option value="pow">Sort by Power &gt; Name</option>
+ <option value="tou">Sort by Toughness &gt; Name</option>
+ <option value="random">Sort by Random</option>
+ <option value="edition">Sort by Edition &gt; Name</option>
+ <option value="issue">Sort by Edition &gt; Collector's Number</option>
+ </optgroup>
+ </select>
+ <input type="submit" value="Search">
+ </td>
+ </tr>
+</table>
+</form>
+<hr>
+
+
+
+<table border="0" cellpadding="0" cellspacing="0" width="100%">
+<tr>
+ <td align="left" width="35%">
+
+
+ &larr; <a href="/frf/en/163.html">Scroll of the Masters</a>
+
+ </td>
+ <td align="center" width="30%">
+ <a href="/frf/en.html">Fate Reforged</a>
+ </td>
+ <td align="right" width="35%">
+
+
+ <a href="/frf/en/165.html">Bloodfell Caves</a> &rarr;
+
+ </td>
+</tr>
+</table>
+<hr />
+
+<table border="0" cellpadding="0" cellspacing="0" width="100%" align="center" style="margin: 0 0 0.5em 0;">
+ <tr>
+ <td width="312" valign="top">
+ <script type="text/javascript" src="http://partner.tcgplayer.com/x3/mchl.ashx?pk=MAGCINFO&amp;sid=95309"></script>
+ <img src="http://magiccards.info/scans/en/frf/164.jpg"
+ alt="Ugin's Construct" width="312" height="445" style="border: 1px solid black;">
+ </td>
+ <td valign="top" style="padding: 0.5em;" width="70%">
+ <span style="font-size: 1.5em;">
+ <a href="/frf/en/164.html">Ugin's Construct</a>
+ <img src="http://magiccards.info/images/en.gif" alt="English"
+ width="16" height="11" class="flag">
+
+ </span>
+
+
+ <p>Artifact Creature — Construct 4/5,
+ 4 (4)
+ </p>
+ <p class="ctext"><b>When Ugin's Construct enters the battlefield, sacrifice a permanent that's one or more colors.</b></p>
+
+
+ <p><i>While trapping the Eldrazi on Zendikar, Ugin learned little from Sorin, but he gleaned the rudiments of lithomancy from Nahiri.</i></p>
+ <p>Illus. Peter Mohrbacher</p>
+ <p><b>Gatherer Card Rulings<a href="http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=391949">?</a>, Legality<a href="http://www.wizards.com/Magic/TCG/Resources.aspx?x=judge/resources/banned">?</a></b></p>
+ <ul><li><b>11/24/2014</b>: If you control only colorless permanents as the ability resolves (for example, basic lands and face-down permanents), you won’t sacrifice anything.</li></ul>
+ <ul>
+
+
+ <li class="legal">Legal in Vintage (Type 1)</li>
+
+
+ <li class="legal">Legal in Legacy (Type 1.5)</li>
+
+ <li class="legal">Legal in Extended (Type 1.X)</li>
+
+ <li class="legal">Legal in Standard (Type 2)</li>
+
+ <!--<li class="legal">Legal in Block Constructed</li>-->
+
+
+ <li class="legal">Legal in Classic (MTGO)</li>
+
+ <li class="legal">Legal in Commander</li>
+
+ <li class="legal">Legal in Modern</li>
+
+ </ul>
+ </td>
+ <td valign="top" style="padding: 0 0.5em;" width="30%">
+ <small>
+
+
+
+
+ <u><b>Printings:</b></u><br>
+
+
+
+ <b>#164 (Peter Mohrbacher)</b><br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <br><u><b>Editions:</b></u><br>
+
+
+
+ <img src="http://magiccards.info/images/en.gif" alt="English"
+ width="16" height="11" class="flag2">
+
+ <b>Fate Reforged (Uncommon)</b><br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <br><u><b>Languages:</b></u><br>
+
+
+
+
+
+ <img src="http://magiccards.info/images/de.gif" alt="German"
+ width="16" height="11" class="flag2">
+ <a href="/frf/de/164.html">Ugins Konstrukt</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/fr.gif" alt="French"
+ width="16" height="11" class="flag2">
+ <a href="/frf/fr/164.html">Construction d'Ugin</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/it.gif" alt="Italian"
+ width="16" height="11" class="flag2">
+ <a href="/frf/it/164.html">Costrutto di Ugin</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/es.gif" alt="Spanish"
+ width="16" height="11" class="flag2">
+ <a href="/frf/es/164.html">Constructo de Ugin</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/pt.gif" alt="Portuguese"
+ width="16" height="11" class="flag2">
+ <a href="/frf/pt/164.html">Constructo de Ugin</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/jp.gif" alt="Japanese"
+ width="16" height="11" class="flag2">
+ <a href="/frf/jp/164.html">ウギンの構築物</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/cn.gif" alt="Simplified Chinese"
+ width="16" height="11" class="flag2">
+ <a href="/frf/cn/164.html">乌金组构体</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/ru.gif" alt="Russian"
+ width="16" height="11" class="flag2">
+ <a href="/frf/ru/164.html">Конструкция Уджина</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/tw.gif" alt="Traditional Chinese"
+ width="16" height="11" class="flag2">
+ <a href="/frf/tw/164.html">烏金組構體</a><br>
+
+
+
+
+ <img src="http://magiccards.info/images/ko.gif" alt="Korean"
+ width="16" height="11" class="flag2">
+ <a href="/frf/ko/164.html">우진의 기계</a><br>
+
+
+
+
+
+ <br><br>
+ <a href="/query?q=%2B%2Bo%21%22Ugin's Construct%22&amp;v=olist">all prints in all languages</a>
+ </small>
+ </td>
+ </tr>
+</table>
+
+<hr />
+<table border="0" cellpadding="0" cellspacing="0" width="95%">
+ <tr>
+ <td valign="top" width="50%">
+ <b>Rules Questions / Links</b><br>
+ <a href="http://magic.tcgplayer.com/db/magic_single_card.asp?cn=Ugin's Construct&amp;partner=MAGCINFO">View All Prices for Ugin's Construct</a><br>
+ <a href="http://magic.tcgplayer.com/db/deck_search_result.asp?CardName=Ugin's Construct&amp;partner=MAGCINFO">View Decks with Ugin's Construct</a><br>
+ <a href="http://crystalkeep.com/cgi-bin/magicsearch.cgi?cardName=Ugin's Construct">Crystal Keep Rulings Summaries</a><br>
+ <a href="http://www.google.com/search?hl=en&amp;q=%22Ugin's Construct%22+site%3Amtgsalvation.com+inurl%3Acranial">Cranial Insertion (MTG Salvation)</a><br>
+
+ <br>
+ <b>MOTL Price Lists</b><br>
+ <a href="http://classic.magictraders.com/cgi-bin/query.cgi?list=magic&amp;field=0&amp;operator=re&amp;target=Ugin's Construct">Non-Foil</a> &middot;
+ <a href="http://classic.magictraders.com/cgi-bin/query.cgi?list=magic-foils&amp;field=0&amp;operator=re&amp;target=Ugin's Construct">Foil</a> &middot;
+ <a href="http://classic.magictraders.com/cgi-bin/query.cgi?list=magic-online&amp;field=0&amp;operator=re&amp;target=Ugin's Construct">MTGO</a><br><br>
+ <b>Print Proxies:</b><br><a href="/proxy?add=scans/en/frf/164&amp;n=1&amp;back=frf/en/164">[ +1 ]</a> <a href="/proxy?add=scans/en/frf/164&amp;n=2&amp;back=frf/en/164">[ +2 ]</a> <a href="/proxy?add=scans/en/frf/164&amp;n=3&amp;back=frf/en/164">[ +3 ]</a> <a href="/proxy?add=scans/en/frf/164&amp;n=4&amp;back=frf/en/164">[ +4 ]</a> </b> &middot; <a href="/proxy?back=frf/en/164">View</a> &middot; <a href="/proxy?clear=true&amp;back=frf/en/164">Clear</a><br><br>
+
+ <b>HTML link to this card</b>:<br><input size="60" value="&lt;a href=&quot;http://magiccards.info/frf/en/164.html&quot;&gt;Ugin's Construct&lt;/a&gt;" onclick="this.select()"><br>
+ <b>BBCode link to this card</b>:<br><input size="60" value="[url=http://magiccards.info/frf/en/164.html]Ugin's Construct[/url]" onclick="this.select()">
+ </td>
+ <td valign="top" width="50%">
+ <script type="text/javascript" src="http://partner.tcgplayer.com/x3/mcpl.ashx?pk=MAGCINFO&amp;sid=95309"></script>
+ </td>
+ </tr>
+</table>
+
+<hr />
+
+<br>
+<small style="color: #aaa;font-size: 0.6em;">
+ The information presented on this site about
+ <b>Magic: The Gathering</b>, both literal and graphical,
+ is copyrighted by Wizards of the Coast.<br>
+ This website is not produced, endorsed, supported,
+ or affiliated with Wizards of the Coast.<!-- <br>
+ <i>Release “Giant Spider”, June 2012</i> --></small>
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-74661-5']);
+ _gaq.push(['_setDomainName', '.magiccards.info'])
+ _gaq.push(['_trackPageview']);
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
+ })();
+ </script>
+</body>
+</html>
+