mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
New puzzle: `Light Up', by James H.
Also in this checkin (committed by mistake - I meant to do it separately), a behind-the-scenes change to Slant to colour the two non-touching classes of diagonals in different colours. Both colours are set to black by default, but configuration by way of SLANT_COLOUR_* can distinguish them if you want. [originally from svn r6164]
This commit is contained in:
5
Recipe
5
Recipe
@ -25,6 +25,7 @@ SLANT = slant dsf
|
|||||||
|
|
||||||
ALL = list NET NETSLIDE cube fifteen sixteen rect pattern solo twiddle
|
ALL = list NET NETSLIDE cube fifteen sixteen rect pattern solo twiddle
|
||||||
+ MINES samegame FLIP guess PEGS dominosa UNTANGLE blackbox SLANT
|
+ MINES samegame FLIP guess PEGS dominosa UNTANGLE blackbox SLANT
|
||||||
|
+ lightup
|
||||||
|
|
||||||
net : [X] gtk COMMON NET
|
net : [X] gtk COMMON NET
|
||||||
netslide : [X] gtk COMMON NETSLIDE
|
netslide : [X] gtk COMMON NETSLIDE
|
||||||
@ -44,6 +45,7 @@ dominosa : [X] gtk COMMON dominosa
|
|||||||
untangle : [X] gtk COMMON UNTANGLE
|
untangle : [X] gtk COMMON UNTANGLE
|
||||||
blackbox : [X] gtk COMMON blackbox
|
blackbox : [X] gtk COMMON blackbox
|
||||||
slant : [X] gtk COMMON SLANT
|
slant : [X] gtk COMMON SLANT
|
||||||
|
lightup : [X] gtk COMMON lightup
|
||||||
|
|
||||||
# Auxiliary command-line programs.
|
# Auxiliary command-line programs.
|
||||||
solosolver : [U] solo[STANDALONE_SOLVER] malloc
|
solosolver : [U] solo[STANDALONE_SOLVER] malloc
|
||||||
@ -74,6 +76,7 @@ dominosa : [G] WINDOWS COMMON dominosa
|
|||||||
untangle : [G] WINDOWS COMMON UNTANGLE
|
untangle : [G] WINDOWS COMMON UNTANGLE
|
||||||
blackbox : [G] WINDOWS COMMON blackbox
|
blackbox : [G] WINDOWS COMMON blackbox
|
||||||
slant : [G] WINDOWS COMMON SLANT
|
slant : [G] WINDOWS COMMON SLANT
|
||||||
|
lightup : [G] WINDOWS COMMON lightup
|
||||||
|
|
||||||
# Mac OS X unified application containing all the puzzles.
|
# Mac OS X unified application containing all the puzzles.
|
||||||
Puzzles : [MX] osx osx.icns osx-info.plist COMMON ALL
|
Puzzles : [MX] osx osx.icns osx-info.plist COMMON ALL
|
||||||
@ -165,7 +168,7 @@ FORCE:
|
|||||||
install:
|
install:
|
||||||
for i in cube net netslide fifteen sixteen twiddle \
|
for i in cube net netslide fifteen sixteen twiddle \
|
||||||
pattern rect solo mines samegame flip guess \
|
pattern rect solo mines samegame flip guess \
|
||||||
pegs dominosa untangle blackbox slant; do \
|
pegs dominosa untangle blackbox slant lightup; do \
|
||||||
$(INSTALL_PROGRAM) -m 755 $$i $(DESTDIR)$(gamesdir)/$$i; \
|
$(INSTALL_PROGRAM) -m 755 $$i $(DESTDIR)$(gamesdir)/$$i; \
|
||||||
done
|
done
|
||||||
!end
|
!end
|
||||||
|
2
list.c
2
list.c
@ -23,6 +23,7 @@ extern const game dominosa;
|
|||||||
extern const game fifteen;
|
extern const game fifteen;
|
||||||
extern const game flip;
|
extern const game flip;
|
||||||
extern const game guess;
|
extern const game guess;
|
||||||
|
extern const game lightup;
|
||||||
extern const game mines;
|
extern const game mines;
|
||||||
extern const game net;
|
extern const game net;
|
||||||
extern const game netslide;
|
extern const game netslide;
|
||||||
@ -43,6 +44,7 @@ const game *gamelist[] = {
|
|||||||
&fifteen,
|
&fifteen,
|
||||||
&flip,
|
&flip,
|
||||||
&guess,
|
&guess,
|
||||||
|
&lightup,
|
||||||
&mines,
|
&mines,
|
||||||
&net,
|
&net,
|
||||||
&netslide,
|
&netslide,
|
||||||
|
57
print.py
57
print.py
@ -418,6 +418,60 @@ def slant_format(s):
|
|||||||
((x)*gridpitch, (h-y)*gridpitch, n))
|
((x)*gridpitch, (h-y)*gridpitch, n))
|
||||||
return ret.coords, ret.s
|
return ret.coords, ret.s
|
||||||
|
|
||||||
|
def lightup_format(s):
|
||||||
|
# Parse the game ID.
|
||||||
|
ret = Holder()
|
||||||
|
ret.s = ""
|
||||||
|
params, seed = string.split(s, ":")
|
||||||
|
w, h = map(string.atoi, string.split(params, "x"))
|
||||||
|
grid = []
|
||||||
|
while len(seed) > 0:
|
||||||
|
if seed[0] in string.lowercase:
|
||||||
|
grid.extend([-2] * (ord(seed[0]) - ord('a') + 1))
|
||||||
|
seed = seed[1:]
|
||||||
|
elif seed[0] == "B":
|
||||||
|
grid.append(-1)
|
||||||
|
seed = seed[1:]
|
||||||
|
elif seed[0] in "01234":
|
||||||
|
grid.append(string.atoi(seed[0]))
|
||||||
|
seed = seed[1:]
|
||||||
|
assert w * h == len(grid)
|
||||||
|
# I'm going to arbitrarily choose to use 9pt text for the
|
||||||
|
# numbers, and a 14pt grid pitch.
|
||||||
|
textht = 10
|
||||||
|
gridpitch = 14
|
||||||
|
# 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 round the grid exterior, thickly.
|
||||||
|
psprint(ret, "newpath 1 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 the internal 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")
|
||||||
|
# And draw the black squares and numbers.
|
||||||
|
psprint(ret, "/Helvetica-Bold findfont %g scalefont setfont" % textht)
|
||||||
|
for y in xrange(h):
|
||||||
|
for x in xrange(w):
|
||||||
|
n = grid[y*w+x]
|
||||||
|
if n >= -1:
|
||||||
|
psprint(ret, ("newpath %g %g moveto 0 %g rlineto " +
|
||||||
|
"%g 0 rlineto 0 %g rlineto closepath fill") % \
|
||||||
|
((x)*gridpitch, (h-1-y)*gridpitch, gridpitch, gridpitch, \
|
||||||
|
-gridpitch))
|
||||||
|
if n >= 0:
|
||||||
|
psprint(ret, "gsave 1 setgray %g %g (%d) ctshow grestore" % \
|
||||||
|
((x+0.5)*gridpitch, (h-y-0.5)*gridpitch, n))
|
||||||
|
return ret.coords, ret.s
|
||||||
|
|
||||||
formatters = {
|
formatters = {
|
||||||
"net": net_format,
|
"net": net_format,
|
||||||
"rect": rect_format,
|
"rect": rect_format,
|
||||||
@ -425,7 +479,8 @@ formatters = {
|
|||||||
"pattern": pattern_format,
|
"pattern": pattern_format,
|
||||||
"solo": solo_format,
|
"solo": solo_format,
|
||||||
"dominosa": dominosa_format,
|
"dominosa": dominosa_format,
|
||||||
"slant": slant_format
|
"slant": slant_format,
|
||||||
|
"lightup": lightup_format
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
|
87
puzzles.but
87
puzzles.but
@ -1476,7 +1476,7 @@ the game entirely with one button if you need to.)
|
|||||||
|
|
||||||
(All the actions described in \k{common-actions} are also available.)
|
(All the actions described in \k{common-actions} are also available.)
|
||||||
|
|
||||||
\H{slant-parameters} \I{parameters, for slant}Slant parameters
|
\H{slant-parameters} \I{parameters, for Slant}Slant parameters
|
||||||
|
|
||||||
These parameters are available from the \q{Custom...} option on the
|
These parameters are available from the \q{Custom...} option on the
|
||||||
\q{Type} menu.
|
\q{Type} menu.
|
||||||
@ -1486,6 +1486,91 @@ These parameters are available from the \q{Custom...} option on the
|
|||||||
\dd Size of grid in squares.
|
\dd Size of grid in squares.
|
||||||
|
|
||||||
|
|
||||||
|
\C{lightup} \i{Light Up}
|
||||||
|
|
||||||
|
\cfg{winhelp-topic}{games.lightup}
|
||||||
|
|
||||||
|
You have a grid of squares. Some are filled in black; some of the
|
||||||
|
black squares are numbered. Your aim is to \q{light up} all the
|
||||||
|
empty squares by placing light bulbs in some of them.
|
||||||
|
|
||||||
|
Each light bulb illuminates the square it is on, plus all squares in
|
||||||
|
line with it horizontally or vertically unless a black square is
|
||||||
|
blocking the way.
|
||||||
|
|
||||||
|
To win the game, you must satisfy the following conditions:
|
||||||
|
|
||||||
|
\b All non-black squares are lit.
|
||||||
|
|
||||||
|
\b No light is lit by another light.
|
||||||
|
|
||||||
|
\b All numbered black squares have exactly that number of lights adjacent to
|
||||||
|
them (in the four squares above, below, and to the side).
|
||||||
|
|
||||||
|
Non-numbered black squares may have any number of lights adjacent to them.
|
||||||
|
|
||||||
|
Credit for this puzzle goes to \i{Nikoli} \k{nikoli-lightup}.
|
||||||
|
|
||||||
|
Light Up was contributed to this collection by James Harvey.
|
||||||
|
|
||||||
|
\B{nikoli-lightup}
|
||||||
|
\W{http://www.nikoli.co.jp/puzzles/32/index-e.htm}\cw{http://www.nikoli.co.jp/puzzles/32/index-e.htm}
|
||||||
|
(beware of Flash)
|
||||||
|
|
||||||
|
\H{lightup-controls} \i{Light Up controls}
|
||||||
|
|
||||||
|
\IM{Light Up controls} controls, for Light Up
|
||||||
|
\IM{Light Up controls} keys, for Light Up
|
||||||
|
\IM{Light Up controls} shortcuts (keyboard), for Light Up
|
||||||
|
|
||||||
|
Left-clicking in a non-black square will toggle the presence of a light
|
||||||
|
in that square. Right-clicking in a non-black square toggles a mark there to aid
|
||||||
|
solving; it can be used to highlight squares that cannot be lit, for example.
|
||||||
|
|
||||||
|
You may not place a light in a marked square, nor place a mark in a lit square.
|
||||||
|
|
||||||
|
The game will highlight obvious errors in red. Lights lit by other
|
||||||
|
lights are highlighted in this way, as are numbered squares which
|
||||||
|
do not (or cannot) have the right number of lights next to them.
|
||||||
|
|
||||||
|
Thus, the grid is solved when all non-black squares have yellow
|
||||||
|
highlights and there are no red lights.
|
||||||
|
|
||||||
|
|
||||||
|
\H{lightup-parameters} \I{parameters, for Light Up}Light Up parameters
|
||||||
|
|
||||||
|
These parameters are available from the \q{Custom...} option on the
|
||||||
|
\q{Type} menu.
|
||||||
|
|
||||||
|
\dt \e{Width}, \e{Height}
|
||||||
|
|
||||||
|
\dd Size of grid in squares.
|
||||||
|
|
||||||
|
\dt \e{%age of black squares}
|
||||||
|
|
||||||
|
\dd Rough percentage of black squares in the grid.
|
||||||
|
|
||||||
|
\lcont{
|
||||||
|
|
||||||
|
This is a hint rather than an instruction. If the grid generator is
|
||||||
|
unable to generate a puzzle to this precise specification, it will
|
||||||
|
increase the proportion of black squares until it can.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
\dt \e{Symmetry}
|
||||||
|
|
||||||
|
\dd Allows you to specify the required symmetry of the black squares
|
||||||
|
in the grid. (This does not affect the difficulty of the puzzles
|
||||||
|
noticeably.)
|
||||||
|
|
||||||
|
\dt \e{Difficulty}
|
||||||
|
|
||||||
|
\dd \q{Easy} means that the puzzles should be soluble without
|
||||||
|
backtracking or guessing, \q{Hard} means that some guesses will
|
||||||
|
probably be necessary.
|
||||||
|
|
||||||
|
|
||||||
\A{licence} \I{MIT licence}\ii{Licence}
|
\A{licence} \I{MIT licence}\ii{Licence}
|
||||||
|
|
||||||
This software is \i{copyright} 2004-2005 Simon Tatham.
|
This software is \i{copyright} 2004-2005 Simon Tatham.
|
||||||
|
53
slant.c
53
slant.c
@ -35,6 +35,8 @@ enum {
|
|||||||
COL_BACKGROUND,
|
COL_BACKGROUND,
|
||||||
COL_GRID,
|
COL_GRID,
|
||||||
COL_INK,
|
COL_INK,
|
||||||
|
COL_SLANT1,
|
||||||
|
COL_SLANT2,
|
||||||
NCOLOURS
|
NCOLOURS
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -982,6 +984,14 @@ static float *game_colours(frontend *fe, game_state *state, int *ncolours)
|
|||||||
ret[COL_INK * 3 + 1] = 0.0F;
|
ret[COL_INK * 3 + 1] = 0.0F;
|
||||||
ret[COL_INK * 3 + 2] = 0.0F;
|
ret[COL_INK * 3 + 2] = 0.0F;
|
||||||
|
|
||||||
|
ret[COL_SLANT1 * 3 + 0] = 0.0F;
|
||||||
|
ret[COL_SLANT1 * 3 + 1] = 0.0F;
|
||||||
|
ret[COL_SLANT1 * 3 + 2] = 0.0F;
|
||||||
|
|
||||||
|
ret[COL_SLANT2 * 3 + 0] = 0.0F;
|
||||||
|
ret[COL_SLANT2 * 3 + 1] = 0.0F;
|
||||||
|
ret[COL_SLANT2 * 3 + 2] = 0.0F;
|
||||||
|
|
||||||
*ncolours = NCOLOURS;
|
*ncolours = NCOLOURS;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1013,14 +1023,14 @@ static void draw_clue(frontend *fe, game_drawstate *ds,
|
|||||||
int x, int y, int v)
|
int x, int y, int v)
|
||||||
{
|
{
|
||||||
char p[2];
|
char p[2];
|
||||||
|
int col = ((x ^ y) & 1) ? COL_SLANT1 : COL_SLANT2;
|
||||||
|
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p[0] = v + '0';
|
p[0] = v + '0';
|
||||||
p[1] = '\0';
|
p[1] = '\0';
|
||||||
draw_circle(fe, COORD(x), COORD(y), CLUE_RADIUS,
|
draw_circle(fe, COORD(x), COORD(y), CLUE_RADIUS, COL_BACKGROUND, col);
|
||||||
COL_BACKGROUND, COL_INK);
|
|
||||||
draw_text(fe, COORD(x), COORD(y), FONT_VARIABLE,
|
draw_text(fe, COORD(x), COORD(y), FONT_VARIABLE,
|
||||||
CLUE_TEXTSIZE, ALIGN_VCENTRE|ALIGN_HCENTRE,
|
CLUE_TEXTSIZE, ALIGN_VCENTRE|ALIGN_HCENTRE,
|
||||||
COL_INK, p);
|
COL_INK, p);
|
||||||
@ -1031,6 +1041,9 @@ static void draw_tile(frontend *fe, game_drawstate *ds, game_clues *clues,
|
|||||||
{
|
{
|
||||||
int w = clues->w /*, h = clues->h*/, W = w+1 /*, H = h+1 */;
|
int w = clues->w /*, h = clues->h*/, W = w+1 /*, H = h+1 */;
|
||||||
int xx, yy;
|
int xx, yy;
|
||||||
|
int chesscolour = (x ^ y) & 1;
|
||||||
|
int fscol = chesscolour ? COL_SLANT2 : COL_SLANT1;
|
||||||
|
int bscol = chesscolour ? COL_SLANT1 : COL_SLANT2;
|
||||||
|
|
||||||
clip(fe, COORD(x), COORD(y), TILESIZE+1, TILESIZE+1);
|
clip(fe, COORD(x), COORD(y), TILESIZE+1, TILESIZE+1);
|
||||||
|
|
||||||
@ -1049,17 +1062,17 @@ static void draw_tile(frontend *fe, game_drawstate *ds, game_clues *clues,
|
|||||||
* Draw the slash.
|
* Draw the slash.
|
||||||
*/
|
*/
|
||||||
if (v & BACKSLASH) {
|
if (v & BACKSLASH) {
|
||||||
draw_line(fe, COORD(x), COORD(y), COORD(x+1), COORD(y+1), COL_INK);
|
draw_line(fe, COORD(x), COORD(y), COORD(x+1), COORD(y+1), bscol);
|
||||||
draw_line(fe, COORD(x)+1, COORD(y), COORD(x+1), COORD(y+1)-1,
|
draw_line(fe, COORD(x)+1, COORD(y), COORD(x+1), COORD(y+1)-1,
|
||||||
COL_INK);
|
bscol);
|
||||||
draw_line(fe, COORD(x), COORD(y)+1, COORD(x+1)-1, COORD(y+1),
|
draw_line(fe, COORD(x), COORD(y)+1, COORD(x+1)-1, COORD(y+1),
|
||||||
COL_INK);
|
bscol);
|
||||||
} else if (v & FORWSLASH) {
|
} else if (v & FORWSLASH) {
|
||||||
draw_line(fe, COORD(x+1), COORD(y), COORD(x), COORD(y+1), COL_INK);
|
draw_line(fe, COORD(x+1), COORD(y), COORD(x), COORD(y+1), fscol);
|
||||||
draw_line(fe, COORD(x+1)-1, COORD(y), COORD(x), COORD(y+1)-1,
|
draw_line(fe, COORD(x+1)-1, COORD(y), COORD(x), COORD(y+1)-1,
|
||||||
COL_INK);
|
fscol);
|
||||||
draw_line(fe, COORD(x+1), COORD(y)+1, COORD(x)+1, COORD(y+1),
|
draw_line(fe, COORD(x+1), COORD(y)+1, COORD(x)+1, COORD(y+1),
|
||||||
COL_INK);
|
fscol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1067,29 +1080,29 @@ static void draw_tile(frontend *fe, game_drawstate *ds, game_clues *clues,
|
|||||||
* neighbouring cell.
|
* neighbouring cell.
|
||||||
*/
|
*/
|
||||||
if (v & L_T)
|
if (v & L_T)
|
||||||
draw_rect(fe, COORD(x), COORD(y)+1, 1, 1, COL_INK);
|
draw_rect(fe, COORD(x), COORD(y)+1, 1, 1, bscol);
|
||||||
if (v & L_B)
|
if (v & L_B)
|
||||||
draw_rect(fe, COORD(x), COORD(y+1)-1, 1, 1, COL_INK);
|
draw_rect(fe, COORD(x), COORD(y+1)-1, 1, 1, fscol);
|
||||||
if (v & R_T)
|
if (v & R_T)
|
||||||
draw_rect(fe, COORD(x+1), COORD(y)+1, 1, 1, COL_INK);
|
draw_rect(fe, COORD(x+1), COORD(y)+1, 1, 1, fscol);
|
||||||
if (v & R_B)
|
if (v & R_B)
|
||||||
draw_rect(fe, COORD(x+1), COORD(y+1)-1, 1, 1, COL_INK);
|
draw_rect(fe, COORD(x+1), COORD(y+1)-1, 1, 1, bscol);
|
||||||
if (v & T_L)
|
if (v & T_L)
|
||||||
draw_rect(fe, COORD(x)+1, COORD(y), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x)+1, COORD(y), 1, 1, bscol);
|
||||||
if (v & T_R)
|
if (v & T_R)
|
||||||
draw_rect(fe, COORD(x+1)-1, COORD(y), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x+1)-1, COORD(y), 1, 1, fscol);
|
||||||
if (v & B_L)
|
if (v & B_L)
|
||||||
draw_rect(fe, COORD(x)+1, COORD(y+1), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x)+1, COORD(y+1), 1, 1, fscol);
|
||||||
if (v & B_R)
|
if (v & B_R)
|
||||||
draw_rect(fe, COORD(x+1)-1, COORD(y+1), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x+1)-1, COORD(y+1), 1, 1, bscol);
|
||||||
if (v & C_TL)
|
if (v & C_TL)
|
||||||
draw_rect(fe, COORD(x), COORD(y), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x), COORD(y), 1, 1, bscol);
|
||||||
if (v & C_TR)
|
if (v & C_TR)
|
||||||
draw_rect(fe, COORD(x+1), COORD(y), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x+1), COORD(y), 1, 1, fscol);
|
||||||
if (v & C_BL)
|
if (v & C_BL)
|
||||||
draw_rect(fe, COORD(x), COORD(y+1), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x), COORD(y+1), 1, 1, fscol);
|
||||||
if (v & C_BR)
|
if (v & C_BR)
|
||||||
draw_rect(fe, COORD(x+1), COORD(y+1), 1, 1, COL_INK);
|
draw_rect(fe, COORD(x+1), COORD(y+1), 1, 1, bscol);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And finally the clues at the corners.
|
* And finally the clues at the corners.
|
||||||
|
Reference in New Issue
Block a user