mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Completely re-engineered version of Loopy, courtesy of Lambros
Lambrou. Now capable of handling triangular and hexagonal grids as well as square ones, and then a number of semiregular plane tilings and duals of semiregular ones. In fact, most of the solver code supports an _arbitrary_ planar graph (well, provided both the graph and its dual have no self-edges), so it could easily be extended further with only a little more effort. [originally from svn r8162]
This commit is contained in:
96
grid.h
Normal file
96
grid.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* (c) Lambros Lambrou 2008
|
||||||
|
*
|
||||||
|
* Code for working with general grids, which can be any planar graph
|
||||||
|
* with faces, edges and vertices (dots). Includes generators for a few
|
||||||
|
* types of grid, including square, hexagonal, triangular and others.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PUZZLES_GRID_H
|
||||||
|
#define PUZZLES_GRID_H
|
||||||
|
|
||||||
|
/* Useful macros */
|
||||||
|
#ifndef SQ
|
||||||
|
# define SQ(x) ( (x) * (x) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
* Grid structures:
|
||||||
|
* A grid is made up of faces, edges and dots. These structures hold
|
||||||
|
* the incidence relationships between these types. For example, an
|
||||||
|
* edge always joins two dots, and is adjacent to two faces.
|
||||||
|
* The "grid_xxx **" members are lists of pointers which are dynamically
|
||||||
|
* allocated during grid generation.
|
||||||
|
* A pointer to a face/edge/dot will always point somewhere inside one of the
|
||||||
|
* three lists of the main "grid" structure: faces, edges, dots.
|
||||||
|
* Could have used integer offsets into these lists, but using actual
|
||||||
|
* pointers instead gives us type-safety.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Need forward declarations */
|
||||||
|
typedef struct grid_face grid_face;
|
||||||
|
typedef struct grid_edge grid_edge;
|
||||||
|
typedef struct grid_dot grid_dot;
|
||||||
|
|
||||||
|
struct grid_face {
|
||||||
|
int order; /* Number of edges, also the number of dots */
|
||||||
|
grid_edge **edges; /* edges around this face */
|
||||||
|
grid_dot **dots; /* corners of this face */
|
||||||
|
};
|
||||||
|
struct grid_edge {
|
||||||
|
grid_dot *dot1, *dot2;
|
||||||
|
grid_face *face1, *face2; /* Use NULL for the infinite outside face */
|
||||||
|
};
|
||||||
|
struct grid_dot {
|
||||||
|
int order;
|
||||||
|
grid_edge **edges;
|
||||||
|
grid_face **faces; /* A NULL grid_face* means infinite outside face */
|
||||||
|
|
||||||
|
/* Position in some fairly arbitrary (Cartesian) coordinate system.
|
||||||
|
* Use large enough values such that we can get away with
|
||||||
|
* integer arithmetic, but small enough such that arithmetic
|
||||||
|
* won't overflow. */
|
||||||
|
int x, y;
|
||||||
|
};
|
||||||
|
typedef struct grid {
|
||||||
|
/* These are (dynamically allocated) arrays of all the
|
||||||
|
* faces, edges, dots that are in the grid. */
|
||||||
|
int num_faces; grid_face *faces;
|
||||||
|
int num_edges; grid_edge *edges;
|
||||||
|
int num_dots; grid_dot *dots;
|
||||||
|
|
||||||
|
/* Should be a face roughly near the middle of the grid.
|
||||||
|
* Used to seed path-generation, and also for nearest-edge
|
||||||
|
* detection. */
|
||||||
|
grid_face *middle_face;
|
||||||
|
|
||||||
|
/* Cache the bounding-box of the grid, so the drawing-code can quickly
|
||||||
|
* figure out the proper scaling to draw onto a given area. */
|
||||||
|
int lowest_x, lowest_y, highest_x, highest_y;
|
||||||
|
|
||||||
|
/* A measure of tile size for this grid (in grid coordinates), to help
|
||||||
|
* the renderer decide how large to draw the grid.
|
||||||
|
* Roughly the size of a single tile - for example the side-length
|
||||||
|
* of a square cell. */
|
||||||
|
int tilesize;
|
||||||
|
|
||||||
|
/* We really don't want to copy this monstrosity!
|
||||||
|
* A grid is immutable once generated.
|
||||||
|
*/
|
||||||
|
int refcount;
|
||||||
|
} grid;
|
||||||
|
|
||||||
|
grid *grid_new_square(int width, int height);
|
||||||
|
grid *grid_new_honeycomb(int width, int height);
|
||||||
|
grid *grid_new_triangular(int width, int height);
|
||||||
|
grid *grid_new_snubsquare(int width, int height);
|
||||||
|
grid *grid_new_cairo(int width, int height);
|
||||||
|
grid *grid_new_greathexagonal(int width, int height);
|
||||||
|
grid *grid_new_octagonal(int width, int height);
|
||||||
|
grid *grid_new_kites(int width, int height);
|
||||||
|
|
||||||
|
void grid_free(grid *g);
|
||||||
|
|
||||||
|
grid_edge *grid_nearest_edge(grid *g, int x, int y);
|
||||||
|
|
||||||
|
#endif /* PUZZLES_GRID_H */
|
6
loopy.R
6
loopy.R
@ -1,10 +1,10 @@
|
|||||||
# -*- makefile -*-
|
# -*- makefile -*-
|
||||||
|
|
||||||
LOOPY = loopy tree234 dsf
|
LOOPY = loopy tree234 dsf grid
|
||||||
|
|
||||||
loopy : [X] GTK COMMON LOOPY loopy-icon|no-icon
|
loopy : [X] GTK COMMON LOOPY loopy-icon|no-icon
|
||||||
|
|
||||||
loopy : [G] WINDOWS COMMON LOOPY loopy.res|noicon.res
|
loopy : [G] WINDOWS COMMON LOOPY loopy.res|noicon.res
|
||||||
|
|
||||||
ALL += LOOPY
|
ALL += LOOPY
|
||||||
|
|
||||||
|
48
puzzles.but
48
puzzles.but
@ -1797,17 +1797,26 @@ Unreasonable puzzles may require guessing and backtracking.
|
|||||||
|
|
||||||
\cfg{winhelp-topic}{games.loopy}
|
\cfg{winhelp-topic}{games.loopy}
|
||||||
|
|
||||||
You are given a grid of dots. Your aim is to draw a single unbroken
|
You are given a grid of dots, marked with yellow lines to indicate
|
||||||
|
which dots you are allowed to connect directly together. Your aim is
|
||||||
|
to use some subset of those yellow lines to draw a single unbroken
|
||||||
loop from dot to dot within the grid.
|
loop from dot to dot within the grid.
|
||||||
|
|
||||||
Some of the square spaces between the dots contain numbers. These
|
Some of the spaces between the lines contain numbers. These numbers
|
||||||
numbers indicate how many of the four edges of that square are part
|
indicate how many of the lines around that space form part of the
|
||||||
of the loop. The loop you draw must correctly satisfy all of these
|
loop. The loop you draw must correctly satisfy all of these clues to
|
||||||
clues to be considered a correct solution.
|
be considered a correct solution.
|
||||||
|
|
||||||
Credit for this puzzle goes to \i{Nikoli} \k{nikoli-loopy}.
|
In the default mode, the dots are arranged in a grid of squares;
|
||||||
|
however, you can also play on triangular or hexagonal grids, or even
|
||||||
|
more exotic ones.
|
||||||
|
|
||||||
Loopy was contributed to this collection by Mike Pinna.
|
Credit for the basic puzzle idea goes to \i{Nikoli}
|
||||||
|
\k{nikoli-loopy}.
|
||||||
|
|
||||||
|
Loopy was originally contributed to this collection by Mike Pinna,
|
||||||
|
and subsequently enhanced to handle various types of non-square grid
|
||||||
|
by Lambros Lambrou.
|
||||||
|
|
||||||
\B{nikoli-loopy}
|
\B{nikoli-loopy}
|
||||||
\W{http://www.nikoli.co.jp/puzzles/3/index-e.htm}\cw{http://www.nikoli.co.jp/puzzles/3/index-e.htm}
|
\W{http://www.nikoli.co.jp/puzzles/3/index-e.htm}\cw{http://www.nikoli.co.jp/puzzles/3/index-e.htm}
|
||||||
@ -1817,12 +1826,14 @@ Loopy was contributed to this collection by Mike Pinna.
|
|||||||
|
|
||||||
\IM{Loopy controls} controls, for Loopy
|
\IM{Loopy controls} controls, for Loopy
|
||||||
|
|
||||||
Click the left mouse button between two dots to add a line segment
|
Click the left mouse button on a yellow line to turn it black,
|
||||||
connecting them. Click again to remove that line segment.
|
indicating that you think it is part of the loop. Click again to
|
||||||
|
turn the line yellow again (meaning you aren't sure yet).
|
||||||
|
|
||||||
If you are sure that a particular line segment is \e{not} part of
|
If you are sure that a particular line segment is \e{not} part of
|
||||||
the loop, you can click the right mouse button to add a small cross
|
the loop, you can click the right mouse button to remove it
|
||||||
indicating this. Click again to remove the cross.
|
completely. Again, clicking a second time will turn the line back to
|
||||||
|
yellow.
|
||||||
|
|
||||||
(All the actions described in \k{common-actions} are also available.)
|
(All the actions described in \k{common-actions} are also available.)
|
||||||
|
|
||||||
@ -1833,7 +1844,20 @@ These parameters are available from the \q{Custom...} option on the
|
|||||||
|
|
||||||
\dt \e{Width}, \e{Height}
|
\dt \e{Width}, \e{Height}
|
||||||
|
|
||||||
\dd Size of grid in squares.
|
\dd Size of grid, measured in number of regions across and down. For
|
||||||
|
square grids, it's clear how this is counted; for other types of
|
||||||
|
grid you may have to think a bit to see how the dimensions are
|
||||||
|
measured.
|
||||||
|
|
||||||
|
\dt \e{Grid type}
|
||||||
|
|
||||||
|
\dd Allows you to choose between a selection of types of tiling.
|
||||||
|
Some have all the faces the same but may have multiple different
|
||||||
|
types of vertex (e.g. the \e{Cairo} or \e{Kites} mode); others have
|
||||||
|
all the vertices the same but may have differnt types of face (e.g.
|
||||||
|
the \e{Great Hexagonal}). The square, triangular and honeycomb grids
|
||||||
|
are fully regular, and have all their vertices \e{and} faces the
|
||||||
|
same; this makes them the least confusing to play.
|
||||||
|
|
||||||
\dt \e{Difficulty}
|
\dt \e{Difficulty}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user