#!/usr/bin/python
+"""
+Play a crossword puzzle in a curses grid. Takes a command line argument of the
+crossword puzzle file.
+"""
+# curses_crossword.py - play crosswords in a terminal
+# Copyright (C) 2009 Brett Parker <iDunno@sommitrealweird.co.uk>
+#
+# 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 2 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import curses
import curses.ascii
"8": unichr(8312).encode(code),
"9": unichr(8313).encode(code),
}
-except:
+except UnicodeError, e:
for number in range(0, 10):
superscript_numbers[str(number)] = str(number)
sys.exit(0)
def parsecrossword(crossworddata):
+ """
+ Read the content of a crossword file in to memory and rejig it in to the 3
+ seperate sections that we expect - namely the grid, the across clues and
+ the down clues.
+ """
ingrid = False
inacross = False
indown = False
if inacross:
if line != "":
parts = line.split()
- question_number = int(parts[0])
+ question_number = int(parts[0].split(",")[0])
clue = " ".join(parts[1:])
crossword["across"][int(question_number)] = \
clue.encode(code)
if indown:
if line != "":
parts = line.split()
- question_number = int(parts[0])
+ question_number = int(parts[0].split(",")[0])
clue = " ".join(parts[1:])
crossword["down"][int(question_number)] = clue.encode(code)
num_cols = len(crossword["grid"][0])
cury += 1
curgridy = 0
for line in crossword["grid"]:
- datastr = ""
curx = 0
curgridx = 0
- for c in line:
+ for curch in line:
stdscr.addch(cury, curx, curses.ACS_VLINE)
if curx > 0:
stdscr.addch(cury+1, curx, curses.ACS_PLUS)
stdscr.addch(cury+1, curx + 2, curses.ACS_HLINE)
stdscr.addch(cury+1, curx + 3, curses.ACS_HLINE)
curx += 1
- if c == "x":
+ if curch == "x":
stdscr.addch(cury, curx, curses.ACS_BLOCK)
stdscr.addch(cury, curx+1, curses.ACS_BLOCK)
stdscr.addch(cury, curx+2, curses.ACS_BLOCK)
curx += 4
curx -= 1
stdscr.addch(cury, curx, curses.ACS_LRCORNER)
- # draw the clues in
+ # draw the clues in (in their own pad)
+ cluespad = curses.newpad( \
+ len(crossword["across"].keys()) \
+ + len(crossword["down"].keys()) \
+ + 3, stdscr.getmaxyx()[1])
cury = (len(crossword["grid"]) * 2) + 1
curx = 0
- stdscr.addstr(cury, curx, "Across")
+ padtlx = curx
+ padtly = cury
+
+ (padbry, padbrx) = stdscr.getmaxyx()
+ if padbry > cluespad.getmaxyx()[0] + padtly:
+ padbry = cluespad.getmaxyx()[0] + padtly
+ cury = 0
+ cluespad.addstr(cury, curx, "Across")
cury += 1
for cluenumber in crossword["across"].keys():
- stdscr.addstr(cury, curx, "%3s: %s" \
+ cluespad.addstr(cury, curx, "%3s: %s" \
%(str(cluenumber), crossword["across"][cluenumber]))
cury += 1
cury += 1
- stdscr.addstr(cury, curx, "Down")
+ cluespad.addstr(cury, curx, "Down")
cury += 1
for cluenumber in crossword["down"].keys():
- stdscr.addstr(cury, curx, "%3s: %s" \
+ cluespad.addstr(cury, curx, "%3s: %s" \
%(str(cluenumber), crossword["down"][cluenumber]))
cury += 1
gridx += 1
stdscr.move(cury, curx)
+ cluescury = 0
+
+ cluespad.refresh(cluescury, 0, padtly, padtlx, padbry - 1, padbrx - 1)
+ cluespad.overlay(stdscr, cluescury, 0, padtly, padtlx, padbry - 1, padbrx - 1)
+
while 1:
- c = stdscr.getch()
- if c == curses.ascii.ESC:
+ inch = stdscr.getch()
+ if inch == curses.ascii.ESC:
break
- if c == curses.KEY_RIGHT:
+ if inch == curses.KEY_NPAGE:
+ if cluescury < cluespad.getmaxyx()[0] - (padbry - padtly):
+ cluescury += 1
+ cluespad.refresh(cluescury, 0, padtly, padtlx, padbry - 1, padbrx - 1)
+ stdscr.refresh()
+ if inch == curses.KEY_PPAGE:
+ if cluescury > 0:
+ cluescury -= 1
+ cluespad.refresh(cluescury, 0, padtly, padtlx, padbry - 1, padbrx - 1)
+ stdscr.refresh()
+ if inch == curses.KEY_RIGHT:
if gridx < (len(crossword["grid"][0]) - 1):
gridx += 1
curx += 4
gridx -= 1
curx -= 4
stdscr.move(cury, curx)
- if c == curses.KEY_LEFT:
+ if inch == curses.KEY_LEFT:
if gridx > 0:
curx -= 4
gridx -= 1
gridx += 1
curx += 4
stdscr.move(cury, curx)
- if c == curses.KEY_UP:
+ if inch == curses.KEY_UP:
if gridy > 0:
gridy -= 1
cury -= 2
gridy += 1
cury += 2
stdscr.move(cury, curx)
- if c == curses.KEY_DOWN:
+ if inch == curses.KEY_DOWN:
if gridy < (len(crossword["grid"]) - 1):
gridy += 1
cury += 2
gridy -= 1
cury -= 2
stdscr.move(cury, curx)
- if curses.ascii.isalpha(c) or c == ord(" "):
- stdscr.addch(cury, curx, c)
+ if curses.ascii.isalpha(inch) or inch == ord(" "):
+ stdscr.addch(cury, curx, inch)
stdscr.move(cury, curx)
- if c == curses.KEY_BACKSPACE or c == curses.KEY_DC:
+ if inch == curses.KEY_BACKSPACE or inch == curses.KEY_DC:
stdscr.addch(cury, curx, ord(" "))
stdscr.move(cury, curx)