-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmakeBoggle.py
More file actions
executable file
·260 lines (206 loc) · 7.49 KB
/
makeBoggle.py
File metadata and controls
executable file
·260 lines (206 loc) · 7.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#!/usr/bin/env python3
#
# makeBoggle.py: Generate and display a Boggle-like game board.
# 2022-07-20: Written by Steven J. DeRose.
#
import sys
import string
import random
__metadata__ = {
"title" : "makeBoggle",
"description" : "Generate and display a Boggle-like game board.",
"rightsHolder" : "Steven J. DeRose",
"creator" : "http://viaf.org/viaf/50334488",
"type" : "http://purl.org/dc/dcmitype/Software",
"language" : "Python 3.7",
"created" : "2022-07-20",
"modified" : "2022-07-20",
"publisher" : "http://github.com/sderose",
"license" : "https://creativecommons.org/licenses/by-sa/3.0/"
}
__version__ = __metadata__["modified"]
descr = """
=Name=
makeBoggle: Generate and display a Boggle-like game board.
=Description=
Generate and display a word-finding game, one of several ways
(chosen with ''--method'').
* OLD: The old commercial Boggle(r) dice
* NEW: The new commercial Boggle(r) dice
* DENSEOLD: "ALESSTIDTERANAME" 842 words
* DENSENEW: "TLGNAEIASTRSDEHB" 906 words
* HIGHOLD: "DSLRETAIPRNTUDES" 2447 points
* HIGHNEW: "TSLNEIAENTRTBESO" 2447 points
* RANDOM: Random, unweighted by letter frequency
* WEIGHTED: a, weighted by letter frequency
* [any letters]: Specified by the user.
By default a 4x4 board is created. The last 3 --method types, however, allow you
to specify a different --size.
==Usage==
makeBoggle.py [options] [files]
=See also=
[http://www.robertgamble.net/2016/01/a-programmers-analysis-of-boggle.html]
=Known bugs and Limitations=
=To do=
* Finish hooking up box-drawing chars.
* Option to colorize letters
* Add options to set width/height.
* Add other output formats, such as HTML.
=History=
* 2022-07-20: Written by Steven J. DeRose.
=Rights=
Copyright 2022-07-20 by Steven J. DeRose. This work is licensed under a
Creative Commons Attribution-Share-alike 3.0 unported license.
See [http://creativecommons.org/licenses/by-sa/3.0/] for more information.
For the most recent version, see [http://www.derose.net/steve/utilities]
or [https://github.com/sderose].
=Options=
"""
# Conceptual box-drawing characters (TODO: Support the real Unicode ones)
boxDraws = {
# name : ( ASCII UHEAVY ),
"HBAR" : ( "-" , "\u2501", ),
"TOP" : ( "-" , "\u2533", ),
"BOT" : ( "-" , "\u253B", ),
"VBAR" : ( "|" , "\u2501", ),
"LEFT" : ( "|" , "\u2523", ),
"RIGHT" : ( "|" , "\u252B", ),
"CROSS" : ( "+" , "\u254B", ),
"ULCORNER" : ( "/" , "\u250F", ),
"URCORNER" : ( "\\" , "\u2513", ),
"LLCORNER" : ( "\\" , "\u2517", ),
"LRCORNER" : ( "/" , "\u251B", ),
}
"""See also Charsets/UnicodeLists/boxDrawing.py.
/---------------\\
| T | O | L | B |
|---+---+---+---|
| E | N | U | T |
|---+---+---+---|
| W | S | J | H |
|---+---+---+---|
| I | T | N | O |
\\---------------/
"""
# name ASCII UHEAVY
HBAR = "-" # \u2501
TOP = "-" # \u2533
BOT = "-" # \u253B
VBAR = "|" # \u2501
LEFT = "|" # \u2523
RIGHT = "|" # \u252B
CROSS = "+" # \u254B
ULCORNER = "/" # \u250F
URCORNER = "\\" # \u2513
LLCORNER = "\\" # \u2517
LRCORNER = "/" # \u251B
oldDice = [
"AACIOT", "AHMORS", "EGKLUY", "ABILTY",
"ACDEMP", "EGINTV", "GILRUW", "ELPSTU",
"DENOSW", "ACELRS", "ABJMOQ", "EEFHIY",
"EHINPS", "DKNOTU", "ADENVZ", "BIFORX"
]
newDice = [
"AAEEGN", "ELRTTY", "AOOTTW", "ABBJOO",
"EHRTVW", "CIMOTU", "DISTTY", "EIOSST",
"DELRVY", "ACHOPS", "HIMNQU", "EEINSU",
"EEGHNW", "AFFKPS", "HLNNRZ", "DEILRX"
]
denseOldBoard = "ALESSTIDTERANAME" # 842 words
denseNewBoard = "TLGNAEIASTRSDEHB" # 906 words
highOldBoard = "DSLRETAIPRNTUDES" # 2447 points
highNewBoard = "TSLNEIAENTRTBESO" # 2447 points
def getBoard(size:int=4, method:str="RANDOM"):
board = ""
if (method == "OLD"): # The old commercial Boggle(r) dice
for d in oldDice:
board += random.choice(d)
elif (method == "NEW"): # The new commercial Boggle(r) dice
for d in newDice:
board += random.choice(d)
elif (method == "RANDOM"): # Random, unweighted by letter frequency
for _i in range(size*size):
board += random.choice(string.ascii_uppercase)
elif (method == "WEIGHTED"): # Random, weighted by letter frequency
assert False, "Weighted choice not finished."
for _i in range(size*size):
board += random.choice(string.ascii_uppercase)
elif (method == "DENSEOLD"):
board = denseOldBoard
elif (method == "DENSENEW"):
board = denseNewBoard
elif (method == "HIGHOLD"):
board = highOldBoard
elif (method == "HIGHNEW"):
board = highNewBoard
else:
if (len(method) != size*size or
not method.isascii() or not method.isletter()):
print("--method is not a named set or --size ** 2 Latin letters.")
sys.exit()
board = method
return board
def showBoard(board:str, size:int=4, cellWidth:int=3, cellHeight:int=1, indent:int=4):
assert len(board) == size*size
# Make the printable parts
# See also my 'align', which knows about Unicode box-drawing chars, too.
iString = " " * indent
vSpace = iString + VBAR
topBar = iString + ULCORNER
midBar = iString + LEFT
botBar = iString + LLCORNER
for _col in range(size):
vSpace += " " * cellWidth + VBAR
topBar += HBAR * cellWidth + TOP
midBar += HBAR * cellWidth + CROSS
botBar += HBAR * cellWidth + BOT
vSpace = vSpace[0:-1] + VBAR
topBar = topBar[0:-1] + URCORNER
midBar = midBar[0:-1] + RIGHT
botBar = botBar[0:-1] + LRCORNER
cellPad = " " * (cellWidth>>1)
cellFormat = cellPad + "%1s" + cellPad + VBAR
for rowStart in range(0, size*size, size):
print(topBar if rowStart == 0 else midBar)
for _s in range(cellHeight>>1): print(vSpace)
rowChars = board[rowStart:rowStart+size]
buf = iString + VBAR
for col in range(size):
buf += cellFormat % (rowChars[col])
print(buf)
for _s in range(cellHeight>>1): print(vSpace)
print(botBar)
return
###############################################################################
# Main
#
if __name__ == "__main__":
import argparse
def processOptions() -> argparse.Namespace:
try:
from BlockFormatter import BlockFormatter
parser = argparse.ArgumentParser(
description=descr, formatter_class=BlockFormatter)
except ImportError:
parser = argparse.ArgumentParser(description=descr)
parser.add_argument(
"--oformat", "--output-format",
type=str, default="ASCII", choices=[ "ASCII", ],
help="How to display the board.")
parser.add_argument(
"--method", type=str, default="OLD",
help="How to generate the board (named method or specific letters).")
parser.add_argument(
"--size", type=int, default=4,
help="What size board to generate (only 4 for now).")
parser.add_argument(
"--version", action="version", version=__version__,
help="Display version information, then exit.")
args0 = parser.parse_args()
args0.method = args0.method.upper()
return(args0)
###########################################################################
#
args = processOptions()
board0 = getBoard(args.size, args.method)
showBoard(board0, args.size)