shithub: puzzles

Download patch

ref: d45d94d355916117cd4c66b050b3ec14c4fbbd4a
parent: 8ddfc3904bb200fa74a383573e1b353ff3143114
author: Simon Tatham <anakin@pobox.com>
date: Sun May 22 07:06:25 EDT 2005

It occurred to me yesterday that Net could perfectly well be played
on paper, so here's a routine to print it out.

[originally from svn r5826]

--- a/print.py
+++ b/print.py
@@ -6,15 +6,15 @@
 # and how many you want per page.
 
 # Supported games are those which are sensibly solvable using
-# pencil and paper: Rectangles, Pattern and Solo.
+# pencil and paper: Rectangles, Pattern, Solo, Net.
 
 # Command-line syntax is
 #
 #     print.py <game-name> <format>
 #
-# <game-name> is one of `rect', `rectangles', `pattern', `solo'.
-# <format> is two numbers separated by an x: `2x3', for example,
-# means two columns by three rows.
+# <game-name> is one of `rect', `rectangles', `pattern', `solo',
+# `net'. <format> is two numbers separated by an x: `2x3', for
+# example, means two columns by three rows.
 #
 # The program will then read game IDs from stdin until it sees EOF,
 # and generate as many PostScript pages on stdout as it needs.
@@ -92,6 +92,111 @@
 		((x+0.5)*gridpitch, (h-y-0.5)*gridpitch, n))
     return ret.coords, ret.s
 
+def net_format(s):
+    # Parse the game ID.
+    ret = Holder()
+    ret.s = ""
+    params, seed = string.split(s, ":")
+    wrapping = 0
+    if params[-1:] == "w":
+	wrapping = 1
+	params = params[:-1]
+    w, h = map(string.atoi, string.split(params, "x"))
+    grid = []
+    hbarriers = []
+    vbarriers = []
+    while len(seed) > 0:
+	n = string.atoi(seed[0], 16)
+	seed = seed[1:]
+	while len(seed) > 0 and seed[0] in 'hv':
+	    x = len(grid) % w
+	    y = len(grid) / w
+	    if seed[0] == 'h':
+		hbarriers.append((x, y+1))
+	    else:
+		vbarriers.append((x+1, y))
+	    seed = seed[1:]
+	grid.append(n)
+    assert w * h == len(grid)
+    # I'm going to arbitrarily choose a 24pt grid pitch.
+    gridpitch = 24
+    scale = 0.25
+    bigoffset = 0.25
+    smalloffset = 0.17
+    # Set up coordinate system.
+    pw = gridpitch * w
+    ph = gridpitch * h
+    ret.coords = (pw/2, pw/2, ph/2, ph/2)
+    psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
+    # Draw the base grid lines.
+    psprint(ret, "newpath 0.02 setlinewidth")
+    for x in xrange(1,w):
+	psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, h * gridpitch))
+    for y in xrange(1,h):
+	psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, w * gridpitch))
+    psprint(ret, "stroke")
+    # Draw round the grid exterior.
+    psprint(ret, "newpath")
+    if not wrapping:
+	psprint(ret, "2 setlinewidth")
+    psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
+    (h * gridpitch, w * gridpitch, -h * gridpitch))
+    psprint(ret, "closepath stroke")
+    # Draw any barriers.
+    psprint(ret, "newpath 2 setlinewidth 1 setlinecap")
+    for x, y in hbarriers:
+	psprint(ret, "%g %g moveto %g 0 rlineto" % \
+	(x * gridpitch, (h - y) * gridpitch, gridpitch))
+    for x, y in vbarriers:
+	psprint(ret, "%g %g moveto 0 -%g rlineto" % \
+	(x * gridpitch, (h - y) * gridpitch, gridpitch))
+    psprint(ret, "stroke")
+    # And draw the symbol in each box.
+    for i in xrange(len(grid)):
+	x = i % w
+	y = i / w
+	v = grid[i]
+	# Rotate to canonical form.
+	if v in (1,2,4,8):
+	    v = 1
+	elif v in (5,10):
+	    v = 5
+	elif v in (3,6,9,12):
+	    v = 9
+	elif v in (7,11,13,14):
+	    v = 13
+	# Centre on an area in the corner of the tile.
+	psprint(ret, "gsave")
+	if v & 4:
+	    hoffset = bigoffset
+	else:
+	    hoffset = smalloffset
+	if v & 2:
+	    voffset = bigoffset
+	else:
+	    voffset = smalloffset
+	psprint(ret, "%g %g translate" % \
+	((x + hoffset) * gridpitch, (h - y - voffset) * gridpitch))
+	psprint(ret, "%g dup scale" % (float(gridpitch) * scale / 2))
+	psprint(ret, "newpath 0.07 setlinewidth")
+	# Draw the radial lines.
+	for dx, dy, z in ((1,0,1), (0,1,2), (-1,0,4), (0,-1,8)):
+	    if v & z:
+		psprint(ret, "0 0 moveto %d %d lineto" % (dx, dy))
+	psprint(ret, "stroke")
+	# Draw additional figures if desired.
+	if v == 13:
+	    # T-pieces have a little circular blob where the lines join.
+	    psprint(ret, "newpath 0 0 0.15 0 360 arc fill")
+	elif v == 1:
+	    # Endpoints have a little empty square at the centre.
+	    psprint(ret, "newpath 0.35 0.35 moveto 0 -0.7 rlineto")
+	    psprint(ret, "-0.7 0 rlineto 0 0.7 rlineto closepath")
+	    psprint(ret, "gsave 1 setgray fill grestore stroke")
+	# Clean up.
+	psprint(ret, "grestore")
+    return ret.coords, ret.s
+
 def pattern_format(s):
     ret = Holder()
     ret.s = ""
@@ -219,6 +324,7 @@
     return ret.coords, ret.s
 
 formatters = {
+"net": net_format,
 "rect": rect_format,
 "rectangles": rect_format,
 "pattern": pattern_format,