path.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /*
  2. * Experimental grid generator for Nikoli's `Number Link' puzzle.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include "puzzles.h"
  9. /*
  10. * 2005-07-08: This is currently a Path grid generator which will
  11. * construct valid grids at a plausible speed. However, the grids
  12. * are not of suitable quality to be used directly as puzzles.
  13. *
  14. * The basic strategy is to start with an empty grid, and
  15. * repeatedly either (a) add a new path to it, or (b) extend one
  16. * end of a path by one square in some direction and push other
  17. * paths into new shapes in the process. The effect of this is that
  18. * we are able to construct a set of paths which between them fill
  19. * the entire grid.
  20. *
  21. * Quality issues: if we set the main loop to do (a) where possible
  22. * and (b) only where necessary, we end up with a grid containing a
  23. * few too many small paths, which therefore doesn't make for an
  24. * interesting puzzle. If we reverse the priority so that we do (b)
  25. * where possible and (a) only where necessary, we end up with some
  26. * staggeringly interwoven grids with very very few separate paths,
  27. * but the result of this is that there's invariably a solution
  28. * other than the intended one which leaves many grid squares
  29. * unfilled. There's also a separate problem which is that many
  30. * grids have really boring and obvious paths in them, such as the
  31. * entire bottom row of the grid being taken up by a single path.
  32. *
  33. * It's not impossible that a few tweaks might eliminate or reduce
  34. * the incidence of boring paths, and might also find a happy
  35. * medium between too many and too few. There remains the question
  36. * of unique solutions, however. I fear there is no alternative but
  37. * to write - somehow! - a solver.
  38. *
  39. * While I'm here, some notes on UI strategy for the parts of the
  40. * puzzle implementation that _aren't_ the generator:
  41. *
  42. * - data model is to track connections between adjacent squares,
  43. * so that you aren't limited to extending a path out from each
  44. * number but can also mark sections of path which you know
  45. * _will_ come in handy later.
  46. *
  47. * - user interface is to click in one square and drag to an
  48. * adjacent one, thus creating a link between them. We can
  49. * probably tolerate rapid mouse motion causing a drag directly
  50. * to a square which is a rook move away, but any other rapid
  51. * motion is ambiguous and probably the best option is to wait
  52. * until the mouse returns to a square we know how to reach.
  53. *
  54. * - a drag causing the current path to backtrack has the effect
  55. * of removing bits of it.
  56. *
  57. * - the UI should enforce at all times the constraint that at
  58. * most two links can come into any square.
  59. *
  60. * - my Cunning Plan for actually implementing this: the game_ui
  61. * contains a grid-sized array, which is copied from the current
  62. * game_state on starting a drag. While a drag is active, the
  63. * contents of the game_ui is adjusted with every mouse motion,
  64. * and is displayed _in place_ of the game_state itself. On
  65. * termination of a drag, the game_ui array is copied back into
  66. * the new game_state (or rather, a string move is encoded which
  67. * has precisely the set of link changes to cause that effect).
  68. */
  69. /*
  70. * 2020-05-11: some thoughts on a solver.
  71. *
  72. * Consider this example puzzle, from Wikipedia:
  73. *
  74. * ---4---
  75. * -3--25-
  76. * ---31--
  77. * ---5---
  78. * -------
  79. * --1----
  80. * 2---4--
  81. *
  82. * The kind of deduction that a human wants to make here is: which way
  83. * does the path between the 4s go? In particular, does it go round
  84. * the left of the W-shaped cluster of endpoints, or round the right
  85. * of it? It's clear at a glance that it must go to the right, because
  86. * _any_ path between the 4s that goes to the left of that cluster, no
  87. * matter what detailed direction it takes, will disconnect the
  88. * remaining grid squares into two components, with the two 2s not in
  89. * the same component. So we immediately know that the path between
  90. * the 4s _must_ go round the right-hand side of the grid.
  91. *
  92. * How do you model that global and topological reasoning in a
  93. * computer?
  94. *
  95. * The most plausible idea I've seen so far is to use fundamental
  96. * groups. The fundamental group of loops based at a given point in a
  97. * space is a free group, under loop concatenation and up to homotopy,
  98. * generated by the loops that go in each direction around each hole
  99. * in the space. In this case, the 'holes' are clues, or connected
  100. * groups of clues.
  101. *
  102. * So you might be able to enumerate all the homotopy classes of paths
  103. * between (say) the two 4s as follows. Start with any old path
  104. * between them (say, find the first one that breadth-first search
  105. * will give you). Choose one of the 4s to regard as the base point
  106. * (arbitrarily). Then breadth-first search among the space of _paths_
  107. * by the following procedure. Given a candidate path, append to it
  108. * each of the possible loops that starts from the base point,
  109. * circumnavigates one clue cluster, and returns to the base point.
  110. * The result will typically be a path that retraces its steps and
  111. * self-intersects. Now adjust it homotopically so that it doesn't. If
  112. * that can't be done, then we haven't generated a fresh candidate
  113. * path; if it can, then we've got a new path that is not homotopic to
  114. * any path we already had, so add it to our list and queue it up to
  115. * become the starting point of this search later.
  116. *
  117. * The idea is that this should exhaustively enumerate, up to
  118. * homotopy, the different ways in which the two 4s can connect to
  119. * each other within the constraint that you have to actually fit the
  120. * path non-self-intersectingly into this grid. Then you can keep a
  121. * list of those homotopy classes in mind, and start ruling them out
  122. * by techniques like the connectivity approach described above.
  123. * Hopefully you end up narrowing down to few enough homotopy classes
  124. * that you can deduce something concrete about actual squares of the
  125. * grid - for example, here, that if the path between 4s has to go
  126. * round the right, then we know some specific squares it must go
  127. * through, so we can fill those in. And then, having filled in a
  128. * piece of the middle of a path, you can now regard connecting the
  129. * ultimate endpoints to that mid-section as two separate subproblems,
  130. * so you've reduced to a simpler instance of the same puzzle.
  131. *
  132. * But I don't know whether all of this actually works. I more or less
  133. * believe the process for enumerating elements of the free group; but
  134. * I'm not as confident that when you find a group element that won't
  135. * fit in the grid, you'll never have to consider its descendants in
  136. * the BFS either. And I'm assuming that 'unwind the self-intersection
  137. * homotopically' is a thing that can actually be turned into a
  138. * sensible algorithm.
  139. *
  140. * --------
  141. *
  142. * Another thing that might be needed is to characterise _which_
  143. * homotopy class a given path is in.
  144. *
  145. * For this I think it's sufficient to choose a collection of paths
  146. * along the _edges_ of the square grid, each of which connects two of
  147. * the holes in the grid (including the grid exterior, which counts as
  148. * a huge hole), such that they form a spanning tree between the
  149. * holes. Then assign each of those paths an orientation, so that
  150. * crossing it in one direction counts as 'positive' and the other
  151. * 'negative'. Now analyse a candidate path from one square to another
  152. * by following it and noting down which of those paths it crosses in
  153. * which direction, then simplifying the result like a free group word
  154. * (i.e. adjacent + and - crossings of the same path cancel out).
  155. *
  156. * --------
  157. *
  158. * If we choose those paths to be of minimal length, then we can get
  159. * an upper bound on the number of homotopy classes by observing that
  160. * you can't traverse any of those barriers more times than will fit
  161. * non-self-intersectingly in the grid. That might be an alternative
  162. * method of bounding the search through the fundamental group to only
  163. * finitely many possibilities.
  164. */
  165. /*
  166. * Standard notation for directions.
  167. */
  168. #define L 0
  169. #define U 1
  170. #define R 2
  171. #define D 3
  172. #define DX(dir) ( (dir)==L ? -1 : (dir)==R ? +1 : 0)
  173. #define DY(dir) ( (dir)==U ? -1 : (dir)==D ? +1 : 0)
  174. /*
  175. * Perform a breadth-first search over a grid of squares with the
  176. * colour of square (X,Y) given by grid[Y*w+X]. The search begins
  177. * at (x,y), and finds all squares which are the same colour as
  178. * (x,y) and reachable from it by orthogonal moves. On return:
  179. * - dist[Y*w+X] gives the distance of (X,Y) from (x,y), or -1 if
  180. * unreachable or a different colour
  181. * - the returned value is the number of reachable squares,
  182. * including (x,y) itself
  183. * - list[0] up to list[returned value - 1] list those squares, in
  184. * increasing order of distance from (x,y) (and in arbitrary
  185. * order within that).
  186. */
  187. static int bfs(int w, int h, int *grid, int x, int y, int *dist, int *list)
  188. {
  189. int i, j, c, listsize, listdone;
  190. /*
  191. * Start by clearing the output arrays.
  192. */
  193. for (i = 0; i < w*h; i++)
  194. dist[i] = list[i] = -1;
  195. /*
  196. * Set up the initial list.
  197. */
  198. listsize = 1;
  199. listdone = 0;
  200. list[0] = y*w+x;
  201. dist[y*w+x] = 0;
  202. c = grid[y*w+x];
  203. /*
  204. * Repeatedly process a square and add any extra squares to the
  205. * end of list.
  206. */
  207. while (listdone < listsize) {
  208. i = list[listdone++];
  209. y = i / w;
  210. x = i % w;
  211. for (j = 0; j < 4; j++) {
  212. int xx, yy, ii;
  213. xx = x + DX(j);
  214. yy = y + DY(j);
  215. ii = yy*w+xx;
  216. if (xx >= 0 && xx < w && yy >= 0 && yy < h &&
  217. grid[ii] == c && dist[ii] == -1) {
  218. dist[ii] = dist[i] + 1;
  219. assert(listsize < w*h);
  220. list[listsize++] = ii;
  221. }
  222. }
  223. }
  224. return listsize;
  225. }
  226. struct genctx {
  227. int w, h;
  228. int *grid, *sparegrid, *sparegrid2, *sparegrid3;
  229. int *dist, *list;
  230. int npaths, pathsize;
  231. int *pathends, *sparepathends; /* 2*npaths entries */
  232. int *pathspare; /* npaths entries */
  233. int *extends; /* 8*npaths entries */
  234. };
  235. static struct genctx *new_genctx(int w, int h)
  236. {
  237. struct genctx *ctx = snew(struct genctx);
  238. ctx->w = w;
  239. ctx->h = h;
  240. ctx->grid = snewn(w * h, int);
  241. ctx->sparegrid = snewn(w * h, int);
  242. ctx->sparegrid2 = snewn(w * h, int);
  243. ctx->sparegrid3 = snewn(w * h, int);
  244. ctx->dist = snewn(w * h, int);
  245. ctx->list = snewn(w * h, int);
  246. ctx->npaths = ctx->pathsize = 0;
  247. ctx->pathends = ctx->sparepathends = ctx->pathspare = ctx->extends = NULL;
  248. return ctx;
  249. }
  250. static void free_genctx(struct genctx *ctx)
  251. {
  252. sfree(ctx->grid);
  253. sfree(ctx->sparegrid);
  254. sfree(ctx->sparegrid2);
  255. sfree(ctx->sparegrid3);
  256. sfree(ctx->dist);
  257. sfree(ctx->list);
  258. sfree(ctx->pathends);
  259. sfree(ctx->sparepathends);
  260. sfree(ctx->pathspare);
  261. sfree(ctx->extends);
  262. }
  263. static int newpath(struct genctx *ctx)
  264. {
  265. int n;
  266. n = ctx->npaths++;
  267. if (ctx->npaths > ctx->pathsize) {
  268. ctx->pathsize += 16;
  269. ctx->pathends = sresize(ctx->pathends, ctx->pathsize*2, int);
  270. ctx->sparepathends = sresize(ctx->sparepathends, ctx->pathsize*2, int);
  271. ctx->pathspare = sresize(ctx->pathspare, ctx->pathsize, int);
  272. ctx->extends = sresize(ctx->extends, ctx->pathsize*8, int);
  273. }
  274. return n;
  275. }
  276. static int is_endpoint(struct genctx *ctx, int x, int y)
  277. {
  278. int w = ctx->w, h = ctx->h, c;
  279. assert(x >= 0 && x < w && y >= 0 && y < h);
  280. c = ctx->grid[y*w+x];
  281. if (c < 0)
  282. return false; /* empty square is not an endpoint! */
  283. assert(c >= 0 && c < ctx->npaths);
  284. if (ctx->pathends[c*2] == y*w+x || ctx->pathends[c*2+1] == y*w+x)
  285. return true;
  286. return false;
  287. }
  288. /*
  289. * Tries to extend a path by one square in the given direction,
  290. * pushing other paths around if necessary. Returns true on success
  291. * or false on failure.
  292. */
  293. static int extend_path(struct genctx *ctx, int path, int end, int direction)
  294. {
  295. int w = ctx->w, h = ctx->h;
  296. int x, y, xe, ye, cut;
  297. int i, j, jp, n, first, last;
  298. assert(path >= 0 && path < ctx->npaths);
  299. assert(end == 0 || end == 1);
  300. /*
  301. * Find the endpoint of the path and the point we plan to
  302. * extend it into.
  303. */
  304. y = ctx->pathends[path * 2 + end] / w;
  305. x = ctx->pathends[path * 2 + end] % w;
  306. assert(x >= 0 && x < w && y >= 0 && y < h);
  307. xe = x + DX(direction);
  308. ye = y + DY(direction);
  309. if (xe < 0 || xe >= w || ye < 0 || ye >= h)
  310. return false; /* could not extend in this direction */
  311. /*
  312. * We don't extend paths _directly_ into endpoints of other
  313. * paths, although we don't mind too much if a knock-on effect
  314. * of an extension is to push part of another path into a third
  315. * path's endpoint.
  316. */
  317. if (is_endpoint(ctx, xe, ye))
  318. return false;
  319. /*
  320. * We can't extend a path back the way it came.
  321. */
  322. if (ctx->grid[ye*w+xe] == path)
  323. return false;
  324. /*
  325. * Paths may not double back on themselves. Check if the new
  326. * point is adjacent to any point of this path other than (x,y).
  327. */
  328. for (j = 0; j < 4; j++) {
  329. int xf, yf;
  330. xf = xe + DX(j);
  331. yf = ye + DY(j);
  332. if (xf >= 0 && xf < w && yf >= 0 && yf < h &&
  333. (xf != x || yf != y) && ctx->grid[yf*w+xf] == path)
  334. return false;
  335. }
  336. /*
  337. * Now we're convinced it's valid to _attempt_ the extension.
  338. * It may still fail if we run out of space to push other paths
  339. * into.
  340. *
  341. * So now we can set up our temporary data structures. We will
  342. * need:
  343. *
  344. * - a spare copy of the grid on which to gradually move paths
  345. * around (sparegrid)
  346. *
  347. * - a second spare copy with which to remember how paths
  348. * looked just before being cut (sparegrid2). FIXME: is
  349. * sparegrid2 necessary? right now it's never different from
  350. * grid itself
  351. *
  352. * - a third spare copy with which to do the internal
  353. * calculations involved in reconstituting a cut path
  354. * (sparegrid3)
  355. *
  356. * - something to track which paths currently need
  357. * reconstituting after being cut, and which have already
  358. * been cut (pathspare)
  359. *
  360. * - a spare copy of pathends to store the altered states in
  361. * (sparepathends)
  362. */
  363. memcpy(ctx->sparegrid, ctx->grid, w*h*sizeof(int));
  364. memcpy(ctx->sparegrid2, ctx->grid, w*h*sizeof(int));
  365. memcpy(ctx->sparepathends, ctx->pathends, ctx->npaths*2*sizeof(int));
  366. for (i = 0; i < ctx->npaths; i++)
  367. ctx->pathspare[i] = 0; /* 0=untouched, 1=broken, 2=fixed */
  368. /*
  369. * Working in sparegrid, actually extend the path. If it cuts
  370. * another, begin a loop in which we restore any cut path by
  371. * moving it out of the way.
  372. */
  373. cut = ctx->sparegrid[ye*w+xe];
  374. ctx->sparegrid[ye*w+xe] = path;
  375. ctx->sparepathends[path*2+end] = ye*w+xe;
  376. ctx->pathspare[path] = 2; /* this one is sacrosanct */
  377. if (cut >= 0) {
  378. assert(cut >= 0 && cut < ctx->npaths);
  379. ctx->pathspare[cut] = 1; /* broken */
  380. while (1) {
  381. for (i = 0; i < ctx->npaths; i++)
  382. if (ctx->pathspare[i] == 1)
  383. break;
  384. if (i == ctx->npaths)
  385. break; /* we're done */
  386. /*
  387. * Path i needs restoring. So walk along its original
  388. * track (as given in sparegrid2) and see where it's
  389. * been cut. Where it has, surround the cut points in
  390. * the same colour, without overwriting already-fixed
  391. * paths.
  392. */
  393. memcpy(ctx->sparegrid3, ctx->sparegrid, w*h*sizeof(int));
  394. n = bfs(w, h, ctx->sparegrid2,
  395. ctx->pathends[i*2] % w, ctx->pathends[i*2] / w,
  396. ctx->dist, ctx->list);
  397. first = last = -1;
  398. if (ctx->sparegrid3[ctx->pathends[i*2]] != i ||
  399. ctx->sparegrid3[ctx->pathends[i*2+1]] != i) return false;/* FIXME */
  400. for (j = 0; j < n; j++) {
  401. jp = ctx->list[j];
  402. assert(ctx->dist[jp] == j);
  403. assert(ctx->sparegrid2[jp] == i);
  404. /*
  405. * Wipe out the original path in sparegrid.
  406. */
  407. if (ctx->sparegrid[jp] == i)
  408. ctx->sparegrid[jp] = -1;
  409. /*
  410. * Be prepared to shorten the path at either end if
  411. * the endpoints have been stomped on.
  412. */
  413. if (ctx->sparegrid3[jp] == i) {
  414. if (first < 0)
  415. first = jp;
  416. last = jp;
  417. }
  418. if (ctx->sparegrid3[jp] != i) {
  419. int jx = jp % w, jy = jp / w;
  420. int dx, dy;
  421. for (dy = -1; dy <= +1; dy++)
  422. for (dx = -1; dx <= +1; dx++) {
  423. int newp, newv;
  424. if (!dy && !dx)
  425. continue; /* central square */
  426. if (jx+dx < 0 || jx+dx >= w ||
  427. jy+dy < 0 || jy+dy >= h)
  428. continue; /* out of range */
  429. newp = (jy+dy)*w+(jx+dx);
  430. newv = ctx->sparegrid3[newp];
  431. if (newv >= 0 && (newv == i ||
  432. ctx->pathspare[newv] == 2))
  433. continue; /* can't use this square */
  434. ctx->sparegrid3[newp] = i;
  435. }
  436. }
  437. }
  438. if (first < 0 || last < 0)
  439. return false; /* path is completely wiped out! */
  440. /*
  441. * Now we've covered sparegrid3 in possible squares for
  442. * the new layout of path i. Find the actual layout
  443. * we're going to use by bfs: we want the shortest path
  444. * from one endpoint to the other.
  445. */
  446. n = bfs(w, h, ctx->sparegrid3, first % w, first / w,
  447. ctx->dist, ctx->list);
  448. if (ctx->dist[last] < 2) {
  449. /*
  450. * Either there is no way to get between the path's
  451. * endpoints, or the remaining endpoints simply
  452. * aren't far enough apart to make the path viable
  453. * any more. This means the entire push operation
  454. * has failed.
  455. */
  456. return false;
  457. }
  458. /*
  459. * Write the new path into sparegrid. Also save the new
  460. * endpoint locations, in case they've changed.
  461. */
  462. jp = last;
  463. j = ctx->dist[jp];
  464. while (1) {
  465. int d;
  466. if (ctx->sparegrid[jp] >= 0) {
  467. if (ctx->pathspare[ctx->sparegrid[jp]] == 2)
  468. return false; /* somehow we've hit a fixed path */
  469. ctx->pathspare[ctx->sparegrid[jp]] = 1; /* broken */
  470. }
  471. ctx->sparegrid[jp] = i;
  472. if (j == 0)
  473. break;
  474. /*
  475. * Now look at the neighbours of jp to find one
  476. * which has dist[] one less.
  477. */
  478. for (d = 0; d < 4; d++) {
  479. int jx = (jp % w) + DX(d), jy = (jp / w) + DY(d);
  480. if (jx >= 0 && jx < w && jy >= 0 && jy < w &&
  481. ctx->dist[jy*w+jx] == j-1) {
  482. jp = jy*w+jx;
  483. j--;
  484. break;
  485. }
  486. }
  487. assert(d < 4);
  488. }
  489. ctx->sparepathends[i*2] = first;
  490. ctx->sparepathends[i*2+1] = last;
  491. /* printf("new ends of path %d: %d,%d\n", i, first, last); */
  492. ctx->pathspare[i] = 2; /* fixed */
  493. }
  494. }
  495. /*
  496. * If we got here, the extension was successful!
  497. */
  498. memcpy(ctx->grid, ctx->sparegrid, w*h*sizeof(int));
  499. memcpy(ctx->pathends, ctx->sparepathends, ctx->npaths*2*sizeof(int));
  500. return true;
  501. }
  502. /*
  503. * Tries to add a new path to the grid.
  504. */
  505. static int add_path(struct genctx *ctx, random_state *rs)
  506. {
  507. int w = ctx->w, h = ctx->h;
  508. int i, ii, n;
  509. /*
  510. * Our strategy is:
  511. * - randomly choose an empty square in the grid
  512. * - do a BFS from that point to find a long path starting
  513. * from it
  514. * - if we run out of viable empty squares, return failure.
  515. */
  516. /*
  517. * Use `sparegrid' to collect a list of empty squares.
  518. */
  519. n = 0;
  520. for (i = 0; i < w*h; i++)
  521. if (ctx->grid[i] == -1)
  522. ctx->sparegrid[n++] = i;
  523. /*
  524. * Shuffle the grid.
  525. */
  526. for (i = n; i-- > 1 ;) {
  527. int k = random_upto(rs, i+1);
  528. if (k != i) {
  529. int t = ctx->sparegrid[i];
  530. ctx->sparegrid[i] = ctx->sparegrid[k];
  531. ctx->sparegrid[k] = t;
  532. }
  533. }
  534. /*
  535. * Loop over it trying to add paths. This looks like a
  536. * horrifying N^4 algorithm (that is, (w*h)^2), but I predict
  537. * that in fact the worst case will very rarely arise because
  538. * when there's lots of grid space an attempt will succeed very
  539. * quickly.
  540. */
  541. for (ii = 0; ii < n; ii++) {
  542. int i = ctx->sparegrid[ii];
  543. int y = i / w, x = i % w, nsq;
  544. int r, c, j;
  545. /*
  546. * BFS from here to find long paths.
  547. */
  548. nsq = bfs(w, h, ctx->grid, x, y, ctx->dist, ctx->list);
  549. /*
  550. * If there aren't any long enough, give up immediately.
  551. */
  552. assert(nsq > 0); /* must be the start square at least! */
  553. if (ctx->dist[ctx->list[nsq-1]] < 3)
  554. continue;
  555. /*
  556. * Find the first viable endpoint in ctx->list (i.e. the
  557. * first point with distance at least three). I could
  558. * binary-search for this, but that would be O(log N)
  559. * whereas in fact I can get a constant time bound by just
  560. * searching up from the start - after all, there can be at
  561. * most 13 points at _less_ than distance 3 from the
  562. * starting one!
  563. */
  564. for (j = 0; j < nsq; j++)
  565. if (ctx->dist[ctx->list[j]] >= 3)
  566. break;
  567. assert(j < nsq); /* we tested above that there was one */
  568. /*
  569. * Now we know that any element of `list' between j and nsq
  570. * would be valid in principle. However, we want a few long
  571. * paths rather than many small ones, so select only those
  572. * elements which are either the maximum length or one
  573. * below it.
  574. */
  575. while (ctx->dist[ctx->list[j]] + 1 < ctx->dist[ctx->list[nsq-1]])
  576. j++;
  577. r = j + random_upto(rs, nsq - j);
  578. j = ctx->list[r];
  579. /*
  580. * And that's our endpoint. Mark the new path on the grid.
  581. */
  582. c = newpath(ctx);
  583. ctx->pathends[c*2] = i;
  584. ctx->pathends[c*2+1] = j;
  585. ctx->grid[j] = c;
  586. while (j != i) {
  587. int d, np, index, pts[4];
  588. np = 0;
  589. for (d = 0; d < 4; d++) {
  590. int xn = (j % w) + DX(d), yn = (j / w) + DY(d);
  591. if (xn >= 0 && xn < w && yn >= 0 && yn < w &&
  592. ctx->dist[yn*w+xn] == ctx->dist[j] - 1)
  593. pts[np++] = yn*w+xn;
  594. }
  595. if (np > 1)
  596. index = random_upto(rs, np);
  597. else
  598. index = 0;
  599. j = pts[index];
  600. ctx->grid[j] = c;
  601. }
  602. return true;
  603. }
  604. return false;
  605. }
  606. /*
  607. * The main grid generation loop.
  608. */
  609. static void gridgen_mainloop(struct genctx *ctx, random_state *rs)
  610. {
  611. int w = ctx->w, h = ctx->h;
  612. int i, n;
  613. /*
  614. * The generation algorithm doesn't always converge. Loop round
  615. * until it does.
  616. */
  617. while (1) {
  618. for (i = 0; i < w*h; i++)
  619. ctx->grid[i] = -1;
  620. ctx->npaths = 0;
  621. while (1) {
  622. /*
  623. * See if the grid is full.
  624. */
  625. for (i = 0; i < w*h; i++)
  626. if (ctx->grid[i] < 0)
  627. break;
  628. if (i == w*h)
  629. return;
  630. #ifdef GENERATION_DIAGNOSTICS
  631. {
  632. int x, y;
  633. for (y = 0; y < h; y++) {
  634. printf("|");
  635. for (x = 0; x < w; x++) {
  636. if (ctx->grid[y*w+x] >= 0)
  637. printf("%2d", ctx->grid[y*w+x]);
  638. else
  639. printf(" .");
  640. }
  641. printf(" |\n");
  642. }
  643. }
  644. #endif
  645. /*
  646. * Try adding a path.
  647. */
  648. if (add_path(ctx, rs)) {
  649. #ifdef GENERATION_DIAGNOSTICS
  650. printf("added path\n");
  651. #endif
  652. continue;
  653. }
  654. /*
  655. * Try extending a path. First list all the possible
  656. * extensions.
  657. */
  658. for (i = 0; i < ctx->npaths * 8; i++)
  659. ctx->extends[i] = i;
  660. n = i;
  661. /*
  662. * Then shuffle the list.
  663. */
  664. for (i = n; i-- > 1 ;) {
  665. int k = random_upto(rs, i+1);
  666. if (k != i) {
  667. int t = ctx->extends[i];
  668. ctx->extends[i] = ctx->extends[k];
  669. ctx->extends[k] = t;
  670. }
  671. }
  672. /*
  673. * Now try each one in turn until one works.
  674. */
  675. for (i = 0; i < n; i++) {
  676. int p, d, e;
  677. p = ctx->extends[i];
  678. d = p % 4;
  679. p /= 4;
  680. e = p % 2;
  681. p /= 2;
  682. #ifdef GENERATION_DIAGNOSTICS
  683. printf("trying to extend path %d end %d (%d,%d) in dir %d\n", p, e,
  684. ctx->pathends[p*2+e] % w,
  685. ctx->pathends[p*2+e] / w, d);
  686. #endif
  687. if (extend_path(ctx, p, e, d)) {
  688. #ifdef GENERATION_DIAGNOSTICS
  689. printf("extended path %d end %d (%d,%d) in dir %d\n", p, e,
  690. ctx->pathends[p*2+e] % w,
  691. ctx->pathends[p*2+e] / w, d);
  692. #endif
  693. break;
  694. }
  695. }
  696. if (i < n)
  697. continue;
  698. break;
  699. }
  700. }
  701. }
  702. /*
  703. * Wrapper function which deals with the boring bits such as
  704. * removing the solution from the generated grid, shuffling the
  705. * numeric labels and creating/disposing of the context structure.
  706. */
  707. static int *gridgen(int w, int h, random_state *rs)
  708. {
  709. struct genctx *ctx;
  710. int *ret;
  711. int i;
  712. ctx = new_genctx(w, h);
  713. gridgen_mainloop(ctx, rs);
  714. /*
  715. * There is likely to be an ordering bias in the numbers
  716. * (longer paths on lower numbers due to there having been more
  717. * grid space when laying them down). So we must shuffle the
  718. * numbers. We use ctx->pathspare for this.
  719. *
  720. * This is also as good a time as any to shift to numbering
  721. * from 1, for display to the user.
  722. */
  723. for (i = 0; i < ctx->npaths; i++)
  724. ctx->pathspare[i] = i+1;
  725. for (i = ctx->npaths; i-- > 1 ;) {
  726. int k = random_upto(rs, i+1);
  727. if (k != i) {
  728. int t = ctx->pathspare[i];
  729. ctx->pathspare[i] = ctx->pathspare[k];
  730. ctx->pathspare[k] = t;
  731. }
  732. }
  733. /* FIXME: remove this at some point! */
  734. {
  735. int y, x;
  736. for (y = 0; y < h; y++) {
  737. printf("|");
  738. for (x = 0; x < w; x++) {
  739. assert(ctx->grid[y*w+x] >= 0);
  740. printf("%2d", ctx->pathspare[ctx->grid[y*w+x]]);
  741. }
  742. printf(" |\n");
  743. }
  744. printf("\n");
  745. }
  746. /*
  747. * Clear the grid, and write in just the endpoints.
  748. */
  749. for (i = 0; i < w*h; i++)
  750. ctx->grid[i] = 0;
  751. for (i = 0; i < ctx->npaths; i++) {
  752. ctx->grid[ctx->pathends[i*2]] =
  753. ctx->grid[ctx->pathends[i*2+1]] = ctx->pathspare[i];
  754. }
  755. ret = ctx->grid;
  756. ctx->grid = NULL;
  757. free_genctx(ctx);
  758. return ret;
  759. }
  760. #ifdef TEST_GEN
  761. #define TEST_GENERAL
  762. int main(void)
  763. {
  764. int w = 10, h = 8;
  765. random_state *rs = random_new("12345", 5);
  766. int x, y, i, *grid;
  767. for (i = 0; i < 10; i++) {
  768. grid = gridgen(w, h, rs);
  769. for (y = 0; y < h; y++) {
  770. printf("|");
  771. for (x = 0; x < w; x++) {
  772. if (grid[y*w+x] > 0)
  773. printf("%2d", grid[y*w+x]);
  774. else
  775. printf(" .");
  776. }
  777. printf(" |\n");
  778. }
  779. printf("\n");
  780. sfree(grid);
  781. }
  782. return 0;
  783. }
  784. #endif