]> git.sommitrealweird.co.uk Git - curses-crossword.git/blob - curses-crossword.py
d11568a2ebedf894e1b70216b1df5688514ef7a7
[curses-crossword.git] / curses-crossword.py
1 #!/usr/bin/python
2
3 import curses
4 import curses.ascii
5 import locale
6 import codecs
7
8 locale.setlocale(locale.LC_ALL, '')
9 code = locale.getpreferredencoding()
10
11 superscript_numbers = {}
12
13 try:
14     superscript_numbers = {
15         "0": unichr(8304).encode(code),
16         "1": unichr(185).encode(code),
17         "2": unichr(178).encode(code),
18         "3": unichr(179).encode(code),
19         "4": unichr(8308).encode(code),
20         "5": unichr(8309).encode(code),
21         "6": unichr(8310).encode(code),
22         "7": unichr(8311).encode(code),
23         "8": unichr(8312).encode(code),
24         "9": unichr(8313).encode(code),
25     }
26 except:
27     for number in range(0,10):
28         superscript_numbers[str(number)] = str(number)
29
30 crossworddata = codecs.open("g2-20090701.txt", "r", "utf-8").read()
31
32 def parsecrossword(crossworddata):
33     ingrid = False
34     inacross = False
35     indown = False
36     crossword = {"grid": [], "across": {}, "down": {}, "grid_questions_start": [], "grid_questions_end": []}
37
38     for line in crossworddata.split("\n"):
39         line = line.strip("\n")
40         if line == "GRID":
41             ingrid = True
42             inacross = False
43             indown = False
44         elif line == "ACROSS":
45             ingrid = False
46             inacross = True
47             indown = False
48         elif line == "DOWN":
49             ingrid = False
50             inacross = False
51             indown = True
52         else:
53             if ingrid:
54                 if line != "":
55                     crossword["grid"].append(line)
56             if inacross:
57                 if line != "":
58                     parts = line.split()
59                     question_number = int(parts[0])
60                     clue = " ".join(parts[1:])
61                     crossword["across"][int(question_number)] = clue
62             if indown:
63                 if line != "":
64                     parts = line.split()
65                     question_number = int(parts[0])
66                     clue = " ".join(parts[1:])
67                     crossword["down"][int(question_number)] = clue
68     num_cols = len(crossword["grid"][0])
69     num_rows = len(crossword["grid"])
70
71     current_clue_number = 1
72
73     for row in range(0,num_rows):
74         crossword["grid_questions_start"].append([])
75
76     for row in range(0,num_rows):
77         for col in range(0,num_cols):
78             have_clue = False
79             if col > 0 \
80                 and crossword["grid"][row][col - 1] == "x" \
81                 and crossword["grid"][row][col] != "x" \
82                 and col < (num_cols - 1) \
83                 and crossword["grid"][row][col + 1] != "x":
84                 have_clue = True
85             if col == 0 and crossword["grid"][row][col] != "x" \
86                 and crossword["grid"][row][col + 1] != "x":
87                 have_clue = True
88             if row > 0 and crossword["grid"][row-1][col] == "x" \
89                 and row < (num_rows - 1) \
90                 and crossword["grid"][row][col] != "x" \
91                 and crossword["grid"][row + 1][col] != "x":
92                 have_clue = True
93             if row == 0 and crossword["grid"][row][col] != "x" \
94                 and crossword["grid"][row + 1][col] != "x":
95                 have_clue = True
96             if have_clue:
97                 crossword["grid_questions_start"][row].append(current_clue_number)
98                 current_clue_number += 1
99             else:
100                 crossword["grid_questions_start"][row].append(0)
101
102     return crossword
103
104 def crossword(stdscr, crossworddata):
105     crossword = parsecrossword(crossworddata)
106     cury = 0
107     grid_length = len(crossword["grid"][0])
108     curx = 0
109     stdscr.addch(cury, curx, curses.ACS_ULCORNER)
110     curx += 1
111     while ((curx - 1) / 4) < grid_length:
112         stdscr.addch(cury, curx, curses.ACS_HLINE)
113         stdscr.addch(cury, curx+1, curses.ACS_HLINE)
114         stdscr.addch(cury, curx+2, curses.ACS_HLINE)
115         stdscr.addch(cury, curx+3, curses.ACS_TTEE)
116         curx += 4
117     curx -= 1
118     stdscr.addch(cury, curx, curses.ACS_URCORNER)
119     cury += 1
120     curgridy=0
121     for line in crossword["grid"]:
122         datastr = ""
123         curx = 0
124         curgridx=0
125         for c in line:
126             stdscr.addch(cury, curx, curses.ACS_VLINE)
127             if curx > 0:
128                 stdscr.addch(cury+1, curx, curses.ACS_PLUS)
129             else:
130                 stdscr.addch(cury+1, curx, curses.ACS_LTEE)
131             stdscr.addch(cury+1, curx + 1, curses.ACS_HLINE)
132             stdscr.addch(cury+1, curx + 2, curses.ACS_HLINE)
133             stdscr.addch(cury+1, curx + 3, curses.ACS_HLINE)
134             curx += 1
135             if c == "x":
136                 stdscr.addch(cury, curx, curses.ACS_BLOCK)
137                 stdscr.addch(cury, curx+1, curses.ACS_BLOCK)
138                 stdscr.addch(cury, curx+2, curses.ACS_BLOCK)
139             elif crossword["grid_questions_start"][curgridy][curgridx] > 0:
140                 stdscr.addstr(cury, curx, ''.join([superscript_numbers[x].decode(code) for x in str(crossword["grid_questions_start"][curgridy][curgridx])]).encode(code))
141             curx += 3
142             curgridx += 1
143         else:
144             stdscr.addch(cury, curx, curses.ACS_VLINE)
145             stdscr.addch(cury + 1, curx, curses.ACS_RTEE)
146         cury += 2
147         curgridy += 1
148     cury -= 1
149     curx = 0
150     stdscr.addch(cury, curx, curses.ACS_LLCORNER)
151     curx += 1
152     while ((curx - 1) / 4) < grid_length:
153         stdscr.addch(cury, curx, curses.ACS_HLINE)
154         stdscr.addch(cury, curx+1, curses.ACS_HLINE)
155         stdscr.addch(cury, curx+2, curses.ACS_HLINE)
156         stdscr.addch(cury, curx+3, curses.ACS_BTEE)
157         curx += 4
158     curx -= 1
159     stdscr.addch(cury, curx, curses.ACS_LRCORNER)
160     # draw the clues in
161     cury = (len(crossword["grid"]) * 2) + 1
162     curx = 0
163     stdscr.addstr(cury, curx, "Across")
164     cury += 1
165     for cluenumber in crossword["across"].keys():
166         stdscr.addstr(cury, curx, "%3s: %s" %(str(cluenumber), crossword["across"][cluenumber]))
167         cury += 1
168
169     cury += 1
170     stdscr.addstr(cury, curx, "Down")
171     cury += 1
172     for cluenumber in crossword["down"].keys():
173         stdscr.addstr(cury, curx, "%3s: %s" %(str(cluenumber), crossword["down"][cluenumber]))
174         cury += 1
175
176     curx = 3
177     cury = 1
178     gridx = 0
179     gridy = 0
180
181     stdscr.move(1,3)
182     while 1:
183         c = stdscr.getch()
184         if c == curses.ascii.ESC:
185             break
186         if c == curses.KEY_RIGHT:
187             if gridx < (len(crossword["grid"][0]) - 1):
188                 gridx += 1
189                 curx += 4
190                 while gridx < (len(crossword["grid"][0]) -1) \
191                     and crossword["grid"][gridy][gridx] == "x":
192                     gridx += 1
193                     curx += 4
194                 while crossword["grid"][gridy][gridx] == "x":
195                     gridx -= 1
196                     curx -= 4
197                 stdscr.move(cury, curx)
198         if c == curses.KEY_LEFT:
199             if gridx > 0:
200                 curx -= 4
201                 gridx -= 1
202                 while gridx > 0 \
203                     and crossword["grid"][gridy][gridx] == "x":
204                         gridx -= 1
205                         curx -= 4
206                 while crossword["grid"][gridy][gridx] == "x":
207                     gridx += 1
208                     curx += 4
209                 stdscr.move(cury, curx)
210         if c == curses.KEY_UP:
211             if gridy > 0:
212                 gridy -= 1
213                 cury -= 2
214                 while gridy > 0 \
215                     and crossword["grid"][gridy][gridx] == "x":
216                         gridy -= 1
217                         cury -= 2
218                 while crossword["grid"][gridy][gridx] == "x":
219                     gridy += 1
220                     cury += 2
221                 stdscr.move(cury, curx)
222         if c == curses.KEY_DOWN:
223             if gridy < (len(crossword["grid"]) - 1):
224                 gridy += 1
225                 cury += 2
226                 while gridy < (len(crossword["grid"]) - 1) \
227                     and crossword["grid"][gridy][gridx] == "x":
228                     gridy += 1
229                     cury += 2
230                 while crossword["grid"][gridy][gridx] == "x":
231                     gridy -= 1
232                     cury -= 2
233                 stdscr.move(cury, curx)
234         if curses.ascii.isalpha(c) or c == ord(" "):
235             stdscr.addch(cury, curx, c)
236             stdscr.move(cury, curx)
237         if c == curses.KEY_BACKSPACE or c == curses.KEY_DC:
238             stdscr.addch(cury, curx, ord(" "))
239             stdscr.move(cury, curx)
240
241
242 curses.wrapper(crossword, crossworddata)