Subject: [xsl] Linear sequence of moves to rectangular board From: Stuart Yeates <stuart.yeates@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 12 May 2005 21:40:37 +0100 (BST) |
I'm transforming a linear sequence of moves into the state of a rectangular board (initially in HTML, images to come, maybe in SVG later). The game I'm modelling is the game of, played with black and white stones on a rectangular grid. Stones can be added and rarely removed. An empty state is sometimes in a transient state called "ko." The attached xml2xhtml.xslt file transforms test1.go.xml into html, with the board in a table and calculates the number of moves and captures for black and white. By passing in different values of $moves, you can step through the moves in the game. I'm aiming for maximum portability and maximum inter-operability. The XML file format is still flexible. I have some questions about where to go from here: (*) In real games $size is normally 19 (but potentially unbounded), and there are approximately 1/2 (size*size) moves per game. My recursive solution has a max depth of (2*size)+(1/2 (size*size)) ~= 200, is this likely to be a problem for any implementations? I'm particular thinking of transformations in browsers. (*) Maybe it's because I'm used to the gracefully recursion of scheme/lisp, but the recursion here feels rather clunky. Am I doing something wrong? (*) I'd like to define calculate a value for $moves (commented out) and use it if no value is passed in on the command line/url, but I can't work out how. This doesn't work: <xsl:if test="$moves = ''"> <xsl:variable name="moves" select="count(//move) -1"/> </xsl:if> as the variable has the wrong scope, and $move access is an error if undefined. So how do I make it robust in the face of bad/missing input from the commandline or url? (*) Currently I'm using explicit "order" attribute. The attribute seems redundant (and potentially error prone), is there a better way to do this? (*) I would like to represent variations, moving from a linear sequence to a sparse tree, as shown in test2.go.xml and test3.go.xml. The desired behavour would be to display at each moves the possible moves following and provide a way to generate the board state for that move, much as incrementing $move does currently. I'm not sure whether restructuring the XML (which is not yet fixed) format would help. Looking at other code and the manuals I have access to the ancestor axis seems like it should be the solution, but I can't quite seem to join up the dots. I can can see that one approach could be to transform test3.go.xml into a format like test1.go.xml, and then to html, but I'm not sure how portable two step transformations are. (*) There are some rather obscure Unicode characters for representing go stones (on the same code-page as the chess pieces). I'm extremely doubtful about their support in a range of browsers, is there a good way to find out how widely they're used? I'm particularly interested in support for them amoung far-east localised windows versions, since this is where most go players are. cheers stuart --------- <?xml version='1.0'?> <!-- xml2xhtml.xslt --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:variable name="size" select="//@dimensiony"/> <!--<xsl:variable name="moves" select="count(//move) -1"/>--> <!-- do the rows --> <xsl:template name="tablerow"> <xsl:param name="rownumber"/> <tr> <xsl:call-template name="tablecolumn"> <xsl:with-param name="columnnumber" select="$size -1"/> <xsl:with-param name="rownumber" select="$rownumber"/> </xsl:call-template> </tr> <xsl:if test="$rownumber > 0"> <xsl:call-template name="tablerow"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber - 1"/> </xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template> <!-- do the columns --> <xsl:template name="tablecolumn"> <xsl:param name="rownumber"/> <xsl:param name="columnnumber"/> <td> <xsl:call-template name="tablecell"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> </xsl:call-template> </td> <xsl:if test="$columnnumber > 0"> <xsl:call-template name="tablecolumn"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber - 1"/> </xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template> <!-- do a single cell --> <xsl:template name="tablecell"> <xsl:param name="rownumber"/> <xsl:param name="columnnumber"/> <xsl:call-template name="tablecellmove"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> <xsl:with-param name="status">empty</xsl:with-param> <xsl:with-param name="move"> <xsl:value-of select="0"/> </xsl:with-param> </xsl:call-template> </xsl:template> <xsl:template name="tablecellmove"> <xsl:param name="rownumber"/> <xsl:param name="columnnumber"/> <xsl:param name="status"/> <xsl:param name="move"/> <!-- <xsl:value-of select="$status"/> --> <xsl:choose> <xsl:when test="$move = $moves"> <xsl:value-of select="$status"/> </xsl:when> <xsl:when test="//move[@order=$move]/ko/vertex[@x=$rownumber][@y=$columnnumber]"> <xsl:call-template name="tablecellmove"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> <xsl:with-param name="status">ko</xsl:with-param> <xsl:with-param name="move"> <xsl:value-of select="$move + 1"/> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:when test="//move[@order=$move]/remove/vertex[@x=$rownumber][@y=$columnnumber]"> <xsl:call-template name="tablecellmove"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> <xsl:with-param name="status">empty</xsl:with-param> <xsl:with-param name="move"> <xsl:value-of select="$move + 1"/> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:when test="//move[@order=$move]/vertex[@x=$rownumber][@y=$columnnumber]"> <xsl:call-template name="tablecellmove"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> <xsl:with-param name="status"> <xsl:value-of select="//move[@order=$move]/@colour"/> </xsl:with-param> <xsl:with-param name="move"> <xsl:value-of select="$move + 1"/> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:when test="$status = 'ko'"> <xsl:call-template name="tablecellmove"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> <xsl:with-param name="status">empty</xsl:with-param> <xsl:with-param name="move"> <xsl:value-of select="$move + 1"/> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:when test="//move[@order=$move]"> <xsl:call-template name="tablecellmove"> <xsl:with-param name="rownumber"> <xsl:value-of select="$rownumber"/> </xsl:with-param> <xsl:with-param name="columnnumber"> <xsl:value-of select="$columnnumber"/> </xsl:with-param> <xsl:with-param name="status"> <xsl:value-of select="$status"/> </xsl:with-param> <xsl:with-param name="move"> <xsl:value-of select="$move + 1"/> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$status"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="game"> <html> <xsl:apply-templates/> <body> <p>Board size: <xsl:value-of select="$size"/></p> <p>Moves: <xsl:value-of select="$moves"/></p> <p>Black captures: <xsl:value-of select="count(//move[@colour = 'black'][@order < $moves]/remove/vertex)"/></p> <p>White captures: <xsl:value-of select="count(//move[@colour = 'white'][@order < $moves]/remove/vertex)"/></p> <table> <xsl:call-template name="tablerow"> <xsl:with-param name="rownumber" select="$size - 1"/> </xsl:call-template> </table> </body> </html> </xsl:template> </xsl:stylesheet> --------- <!-- test1.go.xml --> <?xml version="1.0"?> <?xml-stylesheet type="text/xml" href="xml2xhtml.xslt"?> <game> <board type="rectangular" dimensiony="3" dimensionx="3" /> <move colour="black" order="0" > <vertex x="0" y="1" /> </move> <annotate> <text></text> </annotate> <move colour="white" order="1"> <vertex x="0" y="0" /> </move> <move colour="black" order="2"> <vertex x="1" y="0" /> <remove> <vertex x="0" y="0" /> </remove> <ko> <vertex x="0" y="0" /> </ko> </move> <annotate> <score type="estimated" estimator="gnugo" version="9.7"/> </annotate> <move colour="white" order="3"> <vertex x="1" y="1" /> </move> <move colour="black" order="4"> <vertex x="0" y="0" /> </move> </game> --------- <!-- test2.go.xml --> <?xml version="1.0"?> <?xml-stylesheet type="text/xml" href="./xml2xhtml.xslt"?> <game> <board type="rectangular" dimensiony="4" dimensionx="4" /> <annotation> <text> this is a comment at the start of the file</text> </annotation> <move colour="black" order="0" id="00001"> <vertex x="0" y="1" /> </move> <move colour="white" order="1" id="00002"> <vertex x="0" y="0" /> </move> <move colour="black" order="2" id="00003"> <vertex x="1" y="0" /> <remove> <vertex x="0" y="0" /> </remove> </move> <variation> <move colour="white" order="3" id="00004"> <vertex x="2" y="1" /> </move> <move colour="black" order="4" id="00005"> <vertex x="1" y="1" /> </move> </variation> <variation> <move colour="white" order="3" id="00006"> <vertex x="1" y="1" /> </move> <move colour="black" order="4" id="00007"> <vertex x="0" y="0" /> </move> </variation> </game> --------- <!-- test3.go.xml --> <?xml version="1.0"?> <?xml-stylesheet type="text/xml" href="./xml2xhtml.xslt"?> <game> <board type="rectangular" dimensiony="4" dimensionx="4" /> <annotation> <text> this is a comment at the start of the file</text> </annotation> <move colour="black" order="0" id="00001"> <vertex x="0" y="1" /> </move> <move colour="white" order="1" id="00002"> <vertex x="0" y="0" /> </move> <move colour="black" order="2" id="00003"> <vertex x="1" y="0" /> <remove> <vertex x="0" y="0" /> </remove> </move> <variation> <move colour="white" order="3" id="00004"> <vertex x="2" y="1" /> </move> <variation> <move colour="black" order="4" id="00005"> <vertex x="1" y="1" /> </move> </variation> <variation> <move colour="black" order="4" id="00006"> <vertex x="1" y="2" /> </move> </variation> </variation> <variation> <move colour="white" order="3" id="00007"> <vertex x="1" y="1" /> </move> <move colour="black" order="4" id="00008"> <vertex x="0" y="0" /> </move> </variation> </game>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Re: xsl-list Digest 7 Apr, Michael Kay | Thread | Re: [xsl] Linear sequence of moves , Colin Paul Adams |
Re: [xsl] xsl:apply-templates behav, knocte | Date | [xsl] Better include them in the XS, Dimitre Novatchev |
Month |