dominosa.c 111 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565
  1. /*
  2. * dominosa.c: Domino jigsaw puzzle. Aim to place one of every
  3. * possible domino within a rectangle in such a way that the number
  4. * on each square matches the provided clue.
  5. */
  6. /*
  7. * Further possible deduction types in the solver:
  8. *
  9. * * possibly an advanced form of deduce_parity via 2-connectedness.
  10. * We currently deal with areas of the graph with exactly one way
  11. * in and out; but if you have an area with exactly _two_ routes in
  12. * and out of it, then you can at least decide on the _relative_
  13. * parity of the two (either 'these two edges both bisect dominoes
  14. * or neither do', or 'exactly one of these edges bisects a
  15. * domino'). And occasionally that can be enough to let you rule
  16. * out one of the two remaining choices.
  17. * + For example, if both those edges bisect a domino, then those
  18. * two dominoes would also be both the same.
  19. * + Or perhaps between them they rule out all possibilities for
  20. * some other square.
  21. * + Or perhaps they themselves would be duplicates!
  22. * + Or perhaps, on purely geometric grounds, they would box in a
  23. * square to the point where it ended up having to be an
  24. * isolated singleton.
  25. * + The tricky part of this is how you do the graph theory.
  26. * Perhaps a modified form of Tarjan's bridge-finding algorithm
  27. * would work, but I haven't thought through the details.
  28. *
  29. * * possibly an advanced version of set analysis which doesn't have
  30. * to start from squares all having the same number? For example,
  31. * if you have three mutually non-adjacent squares labelled 1,2,3
  32. * such that the numbers adjacent to each are precisely the other
  33. * two, then set analysis can work just fine in principle, and
  34. * tells you that those three squares must overlap the three
  35. * dominoes 1-2, 2-3 and 1-3 in some order, so you can rule out any
  36. * placements of those elsewhere.
  37. * + the difficulty with this is how you avoid it going painfully
  38. * exponential-time. You can't iterate over all the subsets, so
  39. * you'd need some kind of more sophisticated directed search.
  40. * + and the adjacency allowance has to be similarly accounted
  41. * for, which could get tricky to keep track of.
  42. */
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <assert.h>
  47. #include <ctype.h>
  48. #include <limits.h>
  49. #ifdef NO_TGMATH_H
  50. # include <math.h>
  51. #else
  52. # include <tgmath.h>
  53. #endif
  54. #include "puzzles.h"
  55. /* nth triangular number */
  56. #define TRI(n) ( (n) * ((n) + 1) / 2 )
  57. /* number of dominoes for value n */
  58. #define DCOUNT(n) TRI((n)+1)
  59. /* map a pair of numbers to a unique domino index from 0 upwards. */
  60. #define DINDEX(n1,n2) ( TRI(max(n1,n2)) + min(n1,n2) )
  61. #define FLASH_TIME 0.13F
  62. /*
  63. * Difficulty levels. I do some macro ickery here to ensure that my
  64. * enum and the various forms of my name list always match up.
  65. */
  66. #define DIFFLIST(X) \
  67. X(TRIVIAL,Trivial,t) \
  68. X(BASIC,Basic,b) \
  69. X(HARD,Hard,h) \
  70. X(EXTREME,Extreme,e) \
  71. X(AMBIGUOUS,Ambiguous,a) \
  72. /* end of list */
  73. #define ENUM(upper,title,lower) DIFF_ ## upper,
  74. #define TITLE(upper,title,lower) #title,
  75. #define ENCODE(upper,title,lower) #lower
  76. #define CONFIG(upper,title,lower) ":" #title
  77. enum { DIFFLIST(ENUM) DIFFCOUNT };
  78. static char const *const dominosa_diffnames[] = { DIFFLIST(TITLE) };
  79. static char const dominosa_diffchars[] = DIFFLIST(ENCODE);
  80. #define DIFFCONFIG DIFFLIST(CONFIG)
  81. enum {
  82. COL_BACKGROUND,
  83. COL_TEXT,
  84. COL_DOMINO,
  85. COL_DOMINOCLASH,
  86. COL_DOMINOTEXT,
  87. COL_EDGE,
  88. COL_HIGHLIGHT_1,
  89. COL_HIGHLIGHT_2,
  90. NCOLOURS
  91. };
  92. struct game_params {
  93. int n;
  94. int diff;
  95. };
  96. struct game_numbers {
  97. int refcount;
  98. int *numbers; /* h x w */
  99. };
  100. #define EDGE_L 0x100
  101. #define EDGE_R 0x200
  102. #define EDGE_T 0x400
  103. #define EDGE_B 0x800
  104. struct game_state {
  105. game_params params;
  106. int w, h;
  107. struct game_numbers *numbers;
  108. int *grid;
  109. unsigned short *edges; /* h x w */
  110. bool completed, cheated;
  111. };
  112. static game_params *default_params(void)
  113. {
  114. game_params *ret = snew(game_params);
  115. ret->n = 6;
  116. ret->diff = DIFF_BASIC;
  117. return ret;
  118. }
  119. static const struct game_params dominosa_presets[] = {
  120. { 3, DIFF_TRIVIAL },
  121. { 4, DIFF_TRIVIAL },
  122. { 5, DIFF_TRIVIAL },
  123. { 6, DIFF_TRIVIAL },
  124. { 4, DIFF_BASIC },
  125. { 5, DIFF_BASIC },
  126. { 6, DIFF_BASIC },
  127. { 7, DIFF_BASIC },
  128. { 8, DIFF_BASIC },
  129. { 9, DIFF_BASIC },
  130. { 6, DIFF_HARD },
  131. { 6, DIFF_EXTREME },
  132. };
  133. static bool game_fetch_preset(int i, char **name, game_params **params_out)
  134. {
  135. game_params *params;
  136. char buf[80];
  137. if (i < 0 || i >= lenof(dominosa_presets))
  138. return false;
  139. params = snew(game_params);
  140. *params = dominosa_presets[i]; /* structure copy */
  141. sprintf(buf, "Order %d, %s", params->n, dominosa_diffnames[params->diff]);
  142. *name = dupstr(buf);
  143. *params_out = params;
  144. return true;
  145. }
  146. static void free_params(game_params *params)
  147. {
  148. sfree(params);
  149. }
  150. static game_params *dup_params(const game_params *params)
  151. {
  152. game_params *ret = snew(game_params);
  153. *ret = *params; /* structure copy */
  154. return ret;
  155. }
  156. static void decode_params(game_params *params, char const *string)
  157. {
  158. const char *p = string;
  159. params->n = atoi(p);
  160. while (*p && isdigit((unsigned char)*p)) p++;
  161. while (*p) {
  162. char c = *p++;
  163. if (c == 'a') {
  164. /* Legacy encoding from before the difficulty system */
  165. params->diff = DIFF_AMBIGUOUS;
  166. } else if (c == 'd') {
  167. int i;
  168. params->diff = DIFFCOUNT+1; /* ...which is invalid */
  169. if (*p) {
  170. for (i = 0; i < DIFFCOUNT; i++) {
  171. if (*p == dominosa_diffchars[i])
  172. params->diff = i;
  173. }
  174. p++;
  175. }
  176. }
  177. }
  178. }
  179. static char *encode_params(const game_params *params, bool full)
  180. {
  181. char buf[80];
  182. int len = sprintf(buf, "%d", params->n);
  183. if (full)
  184. len += sprintf(buf + len, "d%c", dominosa_diffchars[params->diff]);
  185. return dupstr(buf);
  186. }
  187. static config_item *game_configure(const game_params *params)
  188. {
  189. config_item *ret;
  190. char buf[80];
  191. ret = snewn(3, config_item);
  192. ret[0].name = "Maximum number on dominoes";
  193. ret[0].type = C_STRING;
  194. sprintf(buf, "%d", params->n);
  195. ret[0].u.string.sval = dupstr(buf);
  196. ret[1].name = "Difficulty";
  197. ret[1].type = C_CHOICES;
  198. ret[1].u.choices.choicenames = DIFFCONFIG;
  199. ret[1].u.choices.selected = params->diff;
  200. ret[2].name = NULL;
  201. ret[2].type = C_END;
  202. return ret;
  203. }
  204. static game_params *custom_params(const config_item *cfg)
  205. {
  206. game_params *ret = snew(game_params);
  207. ret->n = atoi(cfg[0].u.string.sval);
  208. ret->diff = cfg[1].u.choices.selected;
  209. return ret;
  210. }
  211. static const char *validate_params(const game_params *params, bool full)
  212. {
  213. if (params->n < 1)
  214. return "Maximum face number must be at least one";
  215. if (params->n > INT_MAX - 2 ||
  216. params->n + 2 > INT_MAX / (params->n + 1))
  217. return "Maximum face number must not be unreasonably large";
  218. if (params->diff >= DIFFCOUNT)
  219. return "Unknown difficulty rating";
  220. return NULL;
  221. }
  222. /* ----------------------------------------------------------------------
  223. * Solver.
  224. */
  225. #ifdef STANDALONE_SOLVER
  226. #define SOLVER_DIAGNOSTICS
  227. static bool solver_diagnostics = false;
  228. #elif defined SOLVER_DIAGNOSTICS
  229. static const bool solver_diagnostics = true;
  230. #endif
  231. struct solver_domino;
  232. struct solver_placement;
  233. /*
  234. * Information about a particular domino.
  235. */
  236. struct solver_domino {
  237. /* The numbers on the domino, and its index in the dominoes array. */
  238. int lo, hi, index;
  239. /* List of placements not yet ruled out for this domino. */
  240. int nplacements;
  241. struct solver_placement **placements;
  242. #ifdef SOLVER_DIAGNOSTICS
  243. /* A textual name we can easily reuse in solver diagnostics. */
  244. char *name;
  245. #endif
  246. };
  247. /*
  248. * Information about a particular 'placement' (i.e. specific location
  249. * that a domino might go in).
  250. */
  251. struct solver_placement {
  252. /* The index of this placement in sc->placements. */
  253. int index;
  254. /* The two squares that make up this placement. */
  255. struct solver_square *squares[2];
  256. /* The domino that has to go in this position, if any. */
  257. struct solver_domino *domino;
  258. /* The index of this placement in each square's placements array,
  259. * and in that of the domino. */
  260. int spi[2], dpi;
  261. /* Whether this is still considered a possible placement. */
  262. bool active;
  263. /* Other domino placements that overlap with this one. (Maximum 6:
  264. * three overlapping each square of the placement.) */
  265. int noverlaps;
  266. struct solver_placement *overlaps[6];
  267. #ifdef SOLVER_DIAGNOSTICS
  268. /* A textual name we can easily reuse in solver diagnostics. */
  269. char *name;
  270. #endif
  271. };
  272. /*
  273. * Information about a particular solver square.
  274. */
  275. struct solver_square {
  276. /* The coordinates of the square, and its index in a normal grid array. */
  277. int x, y, index;
  278. /* List of domino placements not yet ruled out for this square. */
  279. int nplacements;
  280. struct solver_placement *placements[4];
  281. /* The number in the square. */
  282. int number;
  283. #ifdef SOLVER_DIAGNOSTICS
  284. /* A textual name we can easily reuse in solver diagnostics. */
  285. char *name;
  286. #endif
  287. };
  288. struct solver_scratch {
  289. int n, dc, pc, w, h, wh;
  290. int max_diff_used;
  291. struct solver_domino *dominoes;
  292. struct solver_placement *placements;
  293. struct solver_square *squares;
  294. struct solver_placement **domino_placement_lists;
  295. struct solver_square **squares_by_number;
  296. struct findloopstate *fls;
  297. bool squares_by_number_initialised;
  298. int *wh_scratch, *pc_scratch, *pc_scratch2, *dc_scratch;
  299. DSF *dsf_scratch;
  300. };
  301. static struct solver_scratch *solver_make_scratch(int n)
  302. {
  303. int dc = DCOUNT(n), w = n+2, h = n+1, wh = w*h;
  304. int pc = (w-1)*h + w*(h-1);
  305. struct solver_scratch *sc = snew(struct solver_scratch);
  306. int hi, lo, di, x, y, pi, si;
  307. sc->n = n;
  308. sc->dc = dc;
  309. sc->pc = pc;
  310. sc->w = w;
  311. sc->h = h;
  312. sc->wh = wh;
  313. sc->dominoes = snewn(dc, struct solver_domino);
  314. sc->placements = snewn(pc, struct solver_placement);
  315. sc->squares = snewn(wh, struct solver_square);
  316. sc->domino_placement_lists = snewn(pc, struct solver_placement *);
  317. sc->fls = findloop_new_state(wh);
  318. for (di = hi = 0; hi <= n; hi++) {
  319. for (lo = 0; lo <= hi; lo++) {
  320. assert(di == DINDEX(hi, lo));
  321. sc->dominoes[di].hi = hi;
  322. sc->dominoes[di].lo = lo;
  323. sc->dominoes[di].index = di;
  324. #ifdef SOLVER_DIAGNOSTICS
  325. {
  326. char buf[128];
  327. sprintf(buf, "%d-%d", hi, lo);
  328. sc->dominoes[di].name = dupstr(buf);
  329. }
  330. #endif
  331. di++;
  332. }
  333. }
  334. for (y = 0; y < h; y++) {
  335. for (x = 0; x < w; x++) {
  336. struct solver_square *sq = &sc->squares[y*w+x];
  337. sq->x = x;
  338. sq->y = y;
  339. sq->index = y * w + x;
  340. sq->nplacements = 0;
  341. #ifdef SOLVER_DIAGNOSTICS
  342. {
  343. char buf[128];
  344. sprintf(buf, "(%d,%d)", x, y);
  345. sq->name = dupstr(buf);
  346. }
  347. #endif
  348. }
  349. }
  350. pi = 0;
  351. for (y = 0; y < h-1; y++) {
  352. for (x = 0; x < w; x++) {
  353. assert(pi < pc);
  354. sc->placements[pi].squares[0] = &sc->squares[y*w+x];
  355. sc->placements[pi].squares[1] = &sc->squares[(y+1)*w+x];
  356. #ifdef SOLVER_DIAGNOSTICS
  357. {
  358. char buf[128];
  359. sprintf(buf, "(%d,%d-%d)", x, y, y+1);
  360. sc->placements[pi].name = dupstr(buf);
  361. }
  362. #endif
  363. pi++;
  364. }
  365. }
  366. for (y = 0; y < h; y++) {
  367. for (x = 0; x < w-1; x++) {
  368. assert(pi < pc);
  369. sc->placements[pi].squares[0] = &sc->squares[y*w+x];
  370. sc->placements[pi].squares[1] = &sc->squares[y*w+(x+1)];
  371. #ifdef SOLVER_DIAGNOSTICS
  372. {
  373. char buf[128];
  374. sprintf(buf, "(%d-%d,%d)", x, x+1, y);
  375. sc->placements[pi].name = dupstr(buf);
  376. }
  377. #endif
  378. pi++;
  379. }
  380. }
  381. assert(pi == pc);
  382. /* Set up the full placement lists for all squares, temporarily,
  383. * so as to use them to calculate the overlap lists */
  384. for (si = 0; si < wh; si++)
  385. sc->squares[si].nplacements = 0;
  386. for (pi = 0; pi < pc; pi++) {
  387. struct solver_placement *p = &sc->placements[pi];
  388. for (si = 0; si < 2; si++) {
  389. struct solver_square *sq = p->squares[si];
  390. p->spi[si] = sq->nplacements;
  391. sq->placements[sq->nplacements++] = p;
  392. }
  393. }
  394. /* Actually calculate the overlap lists */
  395. for (pi = 0; pi < pc; pi++) {
  396. struct solver_placement *p = &sc->placements[pi];
  397. p->noverlaps = 0;
  398. for (si = 0; si < 2; si++) {
  399. struct solver_square *sq = p->squares[si];
  400. int j;
  401. for (j = 0; j < sq->nplacements; j++) {
  402. struct solver_placement *q = sq->placements[j];
  403. if (q != p)
  404. p->overlaps[p->noverlaps++] = q;
  405. }
  406. }
  407. }
  408. /* Fill in the index field of the placements */
  409. for (pi = 0; pi < pc; pi++)
  410. sc->placements[pi].index = pi;
  411. /* Lazily initialised by particular solver techniques that might
  412. * never be needed */
  413. sc->squares_by_number = NULL;
  414. sc->squares_by_number_initialised = false;
  415. sc->wh_scratch = NULL;
  416. sc->pc_scratch = sc->pc_scratch2 = NULL;
  417. sc->dc_scratch = NULL;
  418. sc->dsf_scratch = NULL;
  419. return sc;
  420. }
  421. static void solver_free_scratch(struct solver_scratch *sc)
  422. {
  423. #ifdef SOLVER_DIAGNOSTICS
  424. {
  425. int i;
  426. for (i = 0; i < sc->dc; i++)
  427. sfree(sc->dominoes[i].name);
  428. for (i = 0; i < sc->pc; i++)
  429. sfree(sc->placements[i].name);
  430. for (i = 0; i < sc->wh; i++)
  431. sfree(sc->squares[i].name);
  432. }
  433. #endif
  434. sfree(sc->dominoes);
  435. sfree(sc->placements);
  436. sfree(sc->squares);
  437. sfree(sc->domino_placement_lists);
  438. sfree(sc->squares_by_number);
  439. findloop_free_state(sc->fls);
  440. sfree(sc->wh_scratch);
  441. sfree(sc->pc_scratch);
  442. sfree(sc->pc_scratch2);
  443. sfree(sc->dc_scratch);
  444. dsf_free(sc->dsf_scratch);
  445. sfree(sc);
  446. }
  447. static void solver_setup_grid(struct solver_scratch *sc, const int *numbers)
  448. {
  449. int i, j;
  450. for (i = 0; i < sc->wh; i++) {
  451. sc->squares[i].nplacements = 0;
  452. sc->squares[i].number = numbers[sc->squares[i].index];
  453. }
  454. for (i = 0; i < sc->pc; i++) {
  455. struct solver_placement *p = &sc->placements[i];
  456. int di = DINDEX(p->squares[0]->number, p->squares[1]->number);
  457. p->domino = &sc->dominoes[di];
  458. }
  459. for (i = 0; i < sc->dc; i++)
  460. sc->dominoes[i].nplacements = 0;
  461. for (i = 0; i < sc->pc; i++)
  462. sc->placements[i].domino->nplacements++;
  463. for (i = j = 0; i < sc->dc; i++) {
  464. sc->dominoes[i].placements = sc->domino_placement_lists + j;
  465. j += sc->dominoes[i].nplacements;
  466. sc->dominoes[i].nplacements = 0;
  467. }
  468. for (i = 0; i < sc->pc; i++) {
  469. struct solver_placement *p = &sc->placements[i];
  470. p->dpi = p->domino->nplacements;
  471. p->domino->placements[p->domino->nplacements++] = p;
  472. p->active = true;
  473. }
  474. for (i = 0; i < sc->wh; i++)
  475. sc->squares[i].nplacements = 0;
  476. for (i = 0; i < sc->pc; i++) {
  477. struct solver_placement *p = &sc->placements[i];
  478. for (j = 0; j < 2; j++) {
  479. struct solver_square *sq = p->squares[j];
  480. p->spi[j] = sq->nplacements;
  481. sq->placements[sq->nplacements++] = p;
  482. }
  483. }
  484. sc->max_diff_used = DIFF_TRIVIAL;
  485. sc->squares_by_number_initialised = false;
  486. }
  487. /* Given two placements p,q that overlap, returns si such that
  488. * p->squares[si] is the square also in q */
  489. static int common_square_index(struct solver_placement *p,
  490. struct solver_placement *q)
  491. {
  492. return (p->squares[0] == q->squares[0] ||
  493. p->squares[0] == q->squares[1]) ? 0 : 1;
  494. }
  495. /* Sort function used to set up squares_by_number */
  496. static int squares_by_number_cmpfn(const void *av, const void *bv)
  497. {
  498. struct solver_square *a = *(struct solver_square *const *)av;
  499. struct solver_square *b = *(struct solver_square *const *)bv;
  500. return (a->number < b->number ? -1 : a->number > b->number ? +1 :
  501. a->index < b->index ? -1 : a->index > b->index ? +1 : 0);
  502. }
  503. static void rule_out_placement(
  504. struct solver_scratch *sc, struct solver_placement *p)
  505. {
  506. struct solver_domino *d = p->domino;
  507. int i, j, si;
  508. #ifdef SOLVER_DIAGNOSTICS
  509. if (solver_diagnostics)
  510. printf(" ruling out placement %s for domino %s\n", p->name, d->name);
  511. #endif
  512. p->active = false;
  513. i = p->dpi;
  514. assert(d->placements[i] == p);
  515. if (--d->nplacements != i) {
  516. d->placements[i] = d->placements[d->nplacements];
  517. d->placements[i]->dpi = i;
  518. }
  519. for (si = 0; si < 2; si++) {
  520. struct solver_square *sq = p->squares[si];
  521. i = p->spi[si];
  522. assert(sq->placements[i] == p);
  523. if (--sq->nplacements != i) {
  524. sq->placements[i] = sq->placements[sq->nplacements];
  525. j = (sq->placements[i]->squares[0] == sq ? 0 : 1);
  526. sq->placements[i]->spi[j] = i;
  527. }
  528. }
  529. }
  530. /*
  531. * If a domino has only one placement remaining, rule out all other
  532. * placements that overlap it.
  533. */
  534. static bool deduce_domino_single_placement(struct solver_scratch *sc, int di)
  535. {
  536. struct solver_domino *d = &sc->dominoes[di];
  537. struct solver_placement *p, *q;
  538. int oi;
  539. bool done_something = false;
  540. if (d->nplacements != 1)
  541. return false;
  542. p = d->placements[0];
  543. for (oi = 0; oi < p->noverlaps; oi++) {
  544. q = p->overlaps[oi];
  545. if (q->active) {
  546. if (!done_something) {
  547. done_something = true;
  548. #ifdef SOLVER_DIAGNOSTICS
  549. if (solver_diagnostics)
  550. printf("domino %s has unique placement %s\n",
  551. d->name, p->name);
  552. #endif
  553. }
  554. rule_out_placement(sc, q);
  555. }
  556. }
  557. return done_something;
  558. }
  559. /*
  560. * If a square has only one placement remaining, rule out all other
  561. * placements of its domino.
  562. */
  563. static bool deduce_square_single_placement(struct solver_scratch *sc, int si)
  564. {
  565. struct solver_square *sq = &sc->squares[si];
  566. struct solver_placement *p;
  567. struct solver_domino *d;
  568. if (sq->nplacements != 1)
  569. return false;
  570. p = sq->placements[0];
  571. d = p->domino;
  572. if (d->nplacements <= 1)
  573. return false; /* we already knew everything this would tell us */
  574. #ifdef SOLVER_DIAGNOSTICS
  575. if (solver_diagnostics)
  576. printf("square %s has unique placement %s (domino %s)\n",
  577. sq->name, p->name, p->domino->name);
  578. #endif
  579. while (d->nplacements > 1)
  580. rule_out_placement(
  581. sc, d->placements[0] == p ? d->placements[1] : d->placements[0]);
  582. return true;
  583. }
  584. /*
  585. * If all placements for a square involve the same domino, rule out
  586. * all other placements of that domino.
  587. */
  588. static bool deduce_square_single_domino(struct solver_scratch *sc, int si)
  589. {
  590. struct solver_square *sq = &sc->squares[si];
  591. struct solver_domino *d;
  592. int i;
  593. /*
  594. * We only bother with this if the square has at least _two_
  595. * placements. If it only has one, then a simpler deduction will
  596. * have handled it already, or will do so the next time round the
  597. * main solver loop - and we should let the simpler deduction do
  598. * it, because that will give a less overblown diagnostic.
  599. */
  600. if (sq->nplacements < 2)
  601. return false;
  602. d = sq->placements[0]->domino;
  603. for (i = 1; i < sq->nplacements; i++)
  604. if (sq->placements[i]->domino != d)
  605. return false; /* not all the same domino */
  606. if (d->nplacements <= sq->nplacements)
  607. return false; /* no other placements of d to rule out */
  608. #ifdef SOLVER_DIAGNOSTICS
  609. if (solver_diagnostics)
  610. printf("square %s can only contain domino %s\n", sq->name, d->name);
  611. #endif
  612. for (i = d->nplacements; i-- > 0 ;) {
  613. struct solver_placement *p = d->placements[i];
  614. if (p->squares[0] != sq && p->squares[1] != sq)
  615. rule_out_placement(sc, p);
  616. }
  617. return true;
  618. }
  619. /*
  620. * If any placement is overlapped by _all_ possible placements of a
  621. * given domino, rule that placement out.
  622. */
  623. static bool deduce_domino_must_overlap(struct solver_scratch *sc, int di)
  624. {
  625. struct solver_domino *d = &sc->dominoes[di];
  626. struct solver_placement *intersection[6], *p;
  627. int nintersection = 0;
  628. int i, j, k;
  629. /*
  630. * As in deduce_square_single_domino, we only bother with this
  631. * deduction if the domino has at least two placements.
  632. */
  633. if (d->nplacements < 2)
  634. return false;
  635. /* Initialise our set of overlapped placements with all the active
  636. * ones overlapped by placements[0]. */
  637. p = d->placements[0];
  638. for (i = 0; i < p->noverlaps; i++)
  639. if (p->overlaps[i]->active)
  640. intersection[nintersection++] = p->overlaps[i];
  641. /* Now loop over the other placements of d, winnowing that set. */
  642. for (j = 1; j < d->nplacements; j++) {
  643. int old_n;
  644. p = d->placements[j];
  645. old_n = nintersection;
  646. nintersection = 0;
  647. for (k = 0; k < old_n; k++) {
  648. for (i = 0; i < p->noverlaps; i++)
  649. if (p->overlaps[i] == intersection[k])
  650. goto found;
  651. /* If intersection[k] isn't in p->overlaps, exclude it
  652. * from our set of placements overlapped by everything */
  653. continue;
  654. found:
  655. intersection[nintersection++] = intersection[k];
  656. }
  657. }
  658. if (nintersection == 0)
  659. return false; /* no new exclusions */
  660. for (i = 0; i < nintersection; i++) {
  661. p = intersection[i];
  662. #ifdef SOLVER_DIAGNOSTICS
  663. if (solver_diagnostics) {
  664. printf("placement %s of domino %s overlaps all placements "
  665. "of domino %s:", p->name, p->domino->name, d->name);
  666. for (j = 0; j < d->nplacements; j++)
  667. printf(" %s", d->placements[j]->name);
  668. printf("\n");
  669. }
  670. #endif
  671. rule_out_placement(sc, p);
  672. }
  673. return true;
  674. }
  675. /*
  676. * If a placement of domino D overlaps the only remaining placement
  677. * for some square S which is not also for domino D, then placing D
  678. * here would require another copy of it in S, so we can rule it out.
  679. */
  680. static bool deduce_local_duplicate(struct solver_scratch *sc, int pi)
  681. {
  682. struct solver_placement *p = &sc->placements[pi];
  683. struct solver_domino *d = p->domino;
  684. int i, j;
  685. if (!p->active)
  686. return false;
  687. for (i = 0; i < p->noverlaps; i++) {
  688. struct solver_placement *q = p->overlaps[i];
  689. struct solver_square *sq;
  690. if (!q->active)
  691. continue;
  692. /* Find the square of q that _isn't_ part of p */
  693. sq = q->squares[1 - common_square_index(q, p)];
  694. for (j = 0; j < sq->nplacements; j++)
  695. if (sq->placements[j] != q && sq->placements[j]->domino != d)
  696. goto no;
  697. /* If we get here, every possible placement for sq is either q
  698. * itself, or another copy of d. Success! We can rule out p. */
  699. #ifdef SOLVER_DIAGNOSTICS
  700. if (solver_diagnostics) {
  701. printf("placement %s of domino %s would force another copy of %s "
  702. "in square %s\n", p->name, d->name, d->name, sq->name);
  703. }
  704. #endif
  705. rule_out_placement(sc, p);
  706. return true;
  707. no:;
  708. }
  709. return false;
  710. }
  711. /*
  712. * If placement P overlaps one placement for each of two squares S,T
  713. * such that all the remaining placements for both S and T are the
  714. * same domino D (and none of those placements joins S and T to each
  715. * other), then P can't be placed, because it would leave S,T each
  716. * having to be a copy of D, i.e. duplicates.
  717. */
  718. static bool deduce_local_duplicate_2(struct solver_scratch *sc, int pi)
  719. {
  720. struct solver_placement *p = &sc->placements[pi];
  721. int i, j, k;
  722. if (!p->active)
  723. return false;
  724. /*
  725. * Iterate over pairs of placements qi,qj overlapping p.
  726. */
  727. for (i = 0; i < p->noverlaps; i++) {
  728. struct solver_placement *qi = p->overlaps[i];
  729. struct solver_square *sqi;
  730. struct solver_domino *di = NULL;
  731. if (!qi->active)
  732. continue;
  733. /* Find the square of qi that _isn't_ part of p */
  734. sqi = qi->squares[1 - common_square_index(qi, p)];
  735. /*
  736. * Identify the unique domino involved in all possible
  737. * placements of sqi other than qi. If there isn't a unique
  738. * one (either too many or too few), move on and try the next
  739. * qi.
  740. */
  741. for (k = 0; k < sqi->nplacements; k++) {
  742. struct solver_placement *pk = sqi->placements[k];
  743. if (sqi->placements[k] == qi)
  744. continue; /* not counting qi itself */
  745. if (!di)
  746. di = pk->domino;
  747. else if (di != pk->domino)
  748. goto done_qi;
  749. }
  750. if (!di)
  751. goto done_qi;
  752. /*
  753. * Now find an appropriate qj != qi.
  754. */
  755. for (j = 0; j < p->noverlaps; j++) {
  756. struct solver_placement *qj = p->overlaps[j];
  757. struct solver_square *sqj;
  758. bool found_di = false;
  759. if (j == i || !qj->active)
  760. continue;
  761. sqj = qj->squares[1 - common_square_index(qj, p)];
  762. /*
  763. * As above, we want the same domino di to be the only one
  764. * sqj can be if placement qj is ruled out. But also we
  765. * need no placement of sqj to overlap sqi.
  766. */
  767. for (k = 0; k < sqj->nplacements; k++) {
  768. struct solver_placement *pk = sqj->placements[k];
  769. if (pk == qj)
  770. continue; /* not counting qj itself */
  771. if (pk->domino != di)
  772. goto done_qj; /* found a different domino */
  773. if (pk->squares[0] == sqi || pk->squares[1] == sqi)
  774. goto done_qj; /* sqi,sqj can be joined to each other */
  775. found_di = true;
  776. }
  777. if (!found_di)
  778. goto done_qj;
  779. /* If we get here, then every placement for either of sqi
  780. * and sqj is a copy of di, except for the ones that
  781. * overlap p. Success! We can rule out p. */
  782. #ifdef SOLVER_DIAGNOSTICS
  783. if (solver_diagnostics) {
  784. printf("placement %s of domino %s would force squares "
  785. "%s and %s to both be domino %s\n",
  786. p->name, p->domino->name,
  787. sqi->name, sqj->name, di->name);
  788. }
  789. #endif
  790. rule_out_placement(sc, p);
  791. return true;
  792. done_qj:;
  793. }
  794. done_qi:;
  795. }
  796. return false;
  797. }
  798. struct parity_findloop_ctx {
  799. struct solver_scratch *sc;
  800. struct solver_square *sq;
  801. int i;
  802. };
  803. static int parity_neighbour(int vertex, void *vctx)
  804. {
  805. struct parity_findloop_ctx *ctx = (struct parity_findloop_ctx *)vctx;
  806. struct solver_placement *p;
  807. if (vertex >= 0) {
  808. ctx->sq = &ctx->sc->squares[vertex];
  809. ctx->i = 0;
  810. } else {
  811. assert(ctx->sq);
  812. }
  813. if (ctx->i >= ctx->sq->nplacements) {
  814. ctx->sq = NULL;
  815. return -1;
  816. }
  817. p = ctx->sq->placements[ctx->i++];
  818. return p->squares[0]->index + p->squares[1]->index - ctx->sq->index;
  819. }
  820. /*
  821. * Look for dominoes whose placement would disconnect the unfilled
  822. * area of the grid into pieces with odd area. Such a domino can't be
  823. * placed, because then the area on each side of it would be
  824. * untileable.
  825. */
  826. static bool deduce_parity(struct solver_scratch *sc)
  827. {
  828. struct parity_findloop_ctx pflctx;
  829. bool done_something = false;
  830. int pi;
  831. /*
  832. * Run findloop, aka Tarjan's bridge-finding algorithm, on the
  833. * graph whose vertices are squares, with two vertices separated
  834. * by an edge iff some not-yet-ruled-out domino placement covers
  835. * them both. (So each edge itself corresponds to a domino
  836. * placement.)
  837. *
  838. * The effect is that any bridge in this graph is a domino whose
  839. * placement would separate two previously connected areas of the
  840. * unfilled squares of the grid.
  841. *
  842. * Placing that domino would not just disconnect those areas from
  843. * each other, but also use up one square of each. So if we want
  844. * to avoid leaving two odd areas after placing the domino, it
  845. * follows that we want to avoid the bridge having an _even_
  846. * number of vertices on each side.
  847. */
  848. pflctx.sc = sc;
  849. findloop_run(sc->fls, sc->wh, parity_neighbour, &pflctx);
  850. for (pi = 0; pi < sc->pc; pi++) {
  851. struct solver_placement *p = &sc->placements[pi];
  852. int size0, size1;
  853. if (!p->active)
  854. continue;
  855. if (!findloop_is_bridge(
  856. sc->fls, p->squares[0]->index, p->squares[1]->index,
  857. &size0, &size1))
  858. continue;
  859. /* To make a deduction, size0 and size1 must both be even,
  860. * i.e. after placing this domino decrements each by 1 they
  861. * would both become odd and untileable areas. */
  862. if ((size0 | size1) & 1)
  863. continue;
  864. #ifdef SOLVER_DIAGNOSTICS
  865. if (solver_diagnostics) {
  866. printf("placement %s of domino %s would create two odd-sized "
  867. "areas\n", p->name, p->domino->name);
  868. }
  869. #endif
  870. rule_out_placement(sc, p);
  871. done_something = true;
  872. }
  873. return done_something;
  874. }
  875. /*
  876. * Try to find a set of squares all containing the same number, such
  877. * that the set of possible dominoes for all the squares in that set
  878. * is small enough to let us rule out placements of those dominoes
  879. * elsewhere.
  880. */
  881. static bool deduce_set(struct solver_scratch *sc, bool doubles)
  882. {
  883. struct solver_square **sqs, **sqp, **sqe;
  884. int num, nsq, i, j;
  885. unsigned long domino_sets[16], adjacent[16];
  886. struct solver_domino *ds[16];
  887. bool done_something = false;
  888. if (!sc->squares_by_number)
  889. sc->squares_by_number = snewn(sc->wh, struct solver_square *);
  890. if (!sc->wh_scratch)
  891. sc->wh_scratch = snewn(sc->wh, int);
  892. if (!sc->squares_by_number_initialised) {
  893. /*
  894. * If this is the first call to this function for a given
  895. * grid, start by sorting the squares by their containing
  896. * number.
  897. */
  898. for (i = 0; i < sc->wh; i++)
  899. sc->squares_by_number[i] = &sc->squares[i];
  900. qsort(sc->squares_by_number, sc->wh, sizeof(*sc->squares_by_number),
  901. squares_by_number_cmpfn);
  902. }
  903. sqp = sc->squares_by_number;
  904. sqe = sc->squares_by_number + sc->wh;
  905. for (num = 0; num <= sc->n; num++) {
  906. unsigned long squares;
  907. unsigned long squares_done;
  908. /* Find the bounds of the subinterval of squares_by_number
  909. * containing squares with this particular number. */
  910. sqs = sqp;
  911. while (sqp < sqe && (*sqp)->number == num)
  912. sqp++;
  913. nsq = sqp - sqs;
  914. /*
  915. * Now sqs[0], ..., sqs[nsq-1] are the squares containing 'num'.
  916. */
  917. if (nsq > lenof(domino_sets)) {
  918. /*
  919. * Abort this analysis if we're trying to enumerate all
  920. * the subsets of a too-large base set.
  921. *
  922. * This _shouldn't_ happen, at the time of writing this
  923. * code, because the largest puzzle we support is only
  924. * supposed to have 10 instances of each number, and part
  925. * of our input grid validation checks that each number
  926. * does appear the right number of times. But just in case
  927. * weird test input makes its way to this function, or the
  928. * puzzle sizes are expanded later, it's easy enough to
  929. * just rule out doing this analysis for overlarge sets of
  930. * numbers.
  931. */
  932. continue;
  933. }
  934. /*
  935. * Index the squares in wh_scratch, which we're using as a
  936. * lookup table to map the official index of a square back to
  937. * its value in our local indexing scheme.
  938. */
  939. for (i = 0; i < nsq; i++)
  940. sc->wh_scratch[sqs[i]->index] = i;
  941. /*
  942. * For each square, make a bit mask of the dominoes that can
  943. * overlap it, by finding the number at the other end of each
  944. * one.
  945. *
  946. * Also, for each square, make a bit mask of other squares in
  947. * the current list that might occupy the _same_ domino
  948. * (because a possible placement of a double overlaps both).
  949. * We'll need that for evaluating whether sets are properly
  950. * exhaustive.
  951. */
  952. for (i = 0; i < nsq; i++)
  953. adjacent[i] = 0;
  954. for (i = 0; i < nsq; i++) {
  955. struct solver_square *sq = sqs[i];
  956. unsigned long mask = 0;
  957. for (j = 0; j < sq->nplacements; j++) {
  958. struct solver_placement *p = sq->placements[j];
  959. int othernum = p->domino->lo + p->domino->hi - num;
  960. mask |= 1UL << othernum;
  961. ds[othernum] = p->domino; /* so we can find them later */
  962. if (othernum == num) {
  963. /*
  964. * Special case: this is a double, so it gives
  965. * rise to entries in adjacent[].
  966. */
  967. int i2 = sc->wh_scratch[p->squares[0]->index +
  968. p->squares[1]->index - sq->index];
  969. adjacent[i] |= 1UL << i2;
  970. adjacent[i2] |= 1UL << i;
  971. }
  972. }
  973. domino_sets[i] = mask;
  974. }
  975. squares_done = 0;
  976. for (squares = 0; squares < (1UL << nsq); squares++) {
  977. unsigned long dominoes = 0;
  978. int bitpos, nsquares, ndominoes;
  979. bool got_adj_squares = false;
  980. bool reported = false;
  981. bool rule_out_nondoubles;
  982. int min_nused_for_double;
  983. #ifdef SOLVER_DIAGNOSTICS
  984. const char *rule_out_text;
  985. #endif
  986. /*
  987. * We don't do set analysis on the same square of the grid
  988. * more than once in this loop. Otherwise you generate
  989. * pointlessly overcomplicated diagnostics for simpler
  990. * follow-up deductions. For example, suppose squares
  991. * {A,B} must go with dominoes {X,Y}. So you rule out X,Y
  992. * elsewhere, and then it turns out square C (from which
  993. * one of those was eliminated) has only one remaining
  994. * possibility Z. What you _don't_ want to do is
  995. * triumphantly report a second case of set elimination
  996. * where you say 'And also, squares {A,B,C} have to be
  997. * {X,Y,Z}!' You'd prefer to give 'now C has to be Z' as a
  998. * separate deduction later, more simply phrased.
  999. */
  1000. if (squares & squares_done)
  1001. continue;
  1002. nsquares = 0;
  1003. /* Make the set of dominoes that these squares can inhabit. */
  1004. for (bitpos = 0; bitpos < nsq; bitpos++) {
  1005. if (!(1 & (squares >> bitpos)))
  1006. continue; /* this bit isn't set in the mask */
  1007. if (adjacent[bitpos] & squares)
  1008. got_adj_squares = true;
  1009. dominoes |= domino_sets[bitpos];
  1010. nsquares++;
  1011. }
  1012. /* Count them. */
  1013. ndominoes = 0;
  1014. for (bitpos = 0; bitpos < nsq; bitpos++)
  1015. ndominoes += 1 & (dominoes >> bitpos);
  1016. /*
  1017. * Do the two sets have the right relative size?
  1018. */
  1019. if (!got_adj_squares) {
  1020. /*
  1021. * The normal case, in which every possible domino
  1022. * placement involves at most _one_ of these squares.
  1023. *
  1024. * This is exactly analogous to the set analysis
  1025. * deductions in many other puzzles: if our N squares
  1026. * between them have to account for N distinct
  1027. * dominoes, with exactly one of those dominoes to
  1028. * each square, then all those dominoes correspond to
  1029. * all those squares and we can rule out any
  1030. * placements of the same dominoes appearing
  1031. * elsewhere.
  1032. */
  1033. if (ndominoes != nsquares)
  1034. continue;
  1035. rule_out_nondoubles = true;
  1036. min_nused_for_double = 1;
  1037. #ifdef SOLVER_DIAGNOSTICS
  1038. rule_out_text = "all of them elsewhere";
  1039. #endif
  1040. } else {
  1041. if (!doubles)
  1042. continue; /* not at this difficulty level */
  1043. /*
  1044. * But in Dominosa, there's a special case if _two_
  1045. * squares in this set can possibly both be covered by
  1046. * the same double domino. (I.e. if they are adjacent,
  1047. * and moreover, the double-domino placement
  1048. * containing both is not yet ruled out.)
  1049. *
  1050. * In that situation, the simple argument doesn't hold
  1051. * up, because the N squares might be covered by N-1
  1052. * dominoes - or, put another way, if you list the
  1053. * containing domino for each of the squares, they
  1054. * might not be all distinct.
  1055. *
  1056. * In that situation, we can still do something, but
  1057. * the details vary, and there are two further cases.
  1058. */
  1059. if (ndominoes == nsquares-1) {
  1060. /*
  1061. * Suppose there is one _more_ square in our set
  1062. * than there are dominoes it can involve. For
  1063. * example, suppose we had four '0' squares which
  1064. * between them could contain only the 0-0, 0-1
  1065. * and 0-2 dominoes.
  1066. *
  1067. * Then that can only work at all if the 0-0
  1068. * covers two of those squares - and in that
  1069. * situation that _must_ be what's happened.
  1070. *
  1071. * So we can rule out the 0-1 and 0-2 dominoes (in
  1072. * this example) in any placement that doesn't use
  1073. * one of the squares in this set. And we can rule
  1074. * out a placement of the 0-0 even if it uses
  1075. * _one_ square from this set: in this situation,
  1076. * we have to insist on it using _two_.
  1077. */
  1078. rule_out_nondoubles = true;
  1079. min_nused_for_double = 2;
  1080. #ifdef SOLVER_DIAGNOSTICS
  1081. rule_out_text = "all of them elsewhere "
  1082. "(including the double if it fails to use both)";
  1083. #endif
  1084. } else if (ndominoes == nsquares) {
  1085. /*
  1086. * A restricted form of the deduction is still
  1087. * possible if we have the same number of dominoes
  1088. * as squares.
  1089. *
  1090. * If we have _three_ '0' squares none of which
  1091. * can be any domino other than 0-0, 0-1 and 0-2,
  1092. * and there's still a possibility of an 0-0
  1093. * domino using up two of them, then we can't rule
  1094. * out 0-1 or 0-2 anywhere else, because it's
  1095. * possible that these three squares only use two
  1096. * of the dominoes between them.
  1097. *
  1098. * But we _can_ rule out the double 0-0, in any
  1099. * placement that uses _none_ of our three
  1100. * squares. Because we do know that _at least one_
  1101. * of our squares must be involved in the 0-0, or
  1102. * else the three of them would only have the
  1103. * other two dominoes left.
  1104. */
  1105. rule_out_nondoubles = false;
  1106. min_nused_for_double = 1;
  1107. #ifdef SOLVER_DIAGNOSTICS
  1108. rule_out_text = "the double elsewhere";
  1109. #endif
  1110. } else {
  1111. /*
  1112. * If none of those cases has happened, then our
  1113. * set admits no deductions at all.
  1114. */
  1115. continue;
  1116. }
  1117. }
  1118. /* Skip sets of size 1, or whose complement has size 1.
  1119. * Those can be handled by a simpler analysis, and should
  1120. * be, for more sensible solver diagnostics. */
  1121. if (ndominoes <= 1 || ndominoes >= nsq-1)
  1122. continue;
  1123. /*
  1124. * We've found a set! That means we can rule out any
  1125. * placement of any domino in that set which would leave
  1126. * the squares in the set with too few dominoes between
  1127. * them.
  1128. *
  1129. * We may or may not actually end up ruling anything out
  1130. * here. But even if we don't, we should record that these
  1131. * squares form a self-contained set, so that we don't
  1132. * pointlessly report a superset of them later which could
  1133. * instead be reported as just the other ones.
  1134. *
  1135. * Or rather, we do that for the main cases that let us
  1136. * rule out lots of dominoes. We only do this with the
  1137. * borderline case where we can only rule out a double if
  1138. * we _actually_ rule something out. Otherwise we'll never
  1139. * even _find_ a larger set with the same number of
  1140. * dominoes!
  1141. */
  1142. if (rule_out_nondoubles)
  1143. squares_done |= squares;
  1144. for (bitpos = 0; bitpos < nsq; bitpos++) {
  1145. struct solver_domino *d;
  1146. if (!(1 & (dominoes >> bitpos)))
  1147. continue;
  1148. d = ds[bitpos];
  1149. for (i = d->nplacements; i-- > 0 ;) {
  1150. struct solver_placement *p = d->placements[i];
  1151. int si, nused;
  1152. /* Count how many of our squares this placement uses. */
  1153. for (si = nused = 0; si < 2; si++) {
  1154. struct solver_square *sq2 = p->squares[si];
  1155. if (sq2->number == num &&
  1156. (1 & (squares >> sc->wh_scratch[sq2->index])))
  1157. nused++;
  1158. }
  1159. /* See if that's too many to rule it out. */
  1160. if (d->lo == d->hi) {
  1161. if (nused >= min_nused_for_double)
  1162. continue;
  1163. } else {
  1164. if (nused > 0 || !rule_out_nondoubles)
  1165. continue;
  1166. }
  1167. if (!reported) {
  1168. reported = true;
  1169. done_something = true;
  1170. /* In case we didn't do this above */
  1171. squares_done |= squares;
  1172. #ifdef SOLVER_DIAGNOSTICS
  1173. if (solver_diagnostics) {
  1174. int b;
  1175. const char *sep;
  1176. printf("squares {");
  1177. for (sep = "", b = 0; b < nsq; b++)
  1178. if (1 & (squares >> b)) {
  1179. printf("%s%s", sep, sqs[b]->name);
  1180. sep = ",";
  1181. }
  1182. printf("} can contain only dominoes {");
  1183. for (sep = "", b = 0; b < nsq; b++)
  1184. if (1 & (dominoes >> b)) {
  1185. printf("%s%s", sep, ds[b]->name);
  1186. sep = ",";
  1187. }
  1188. printf("}, so rule out %s", rule_out_text);
  1189. printf("\n");
  1190. }
  1191. #endif
  1192. }
  1193. rule_out_placement(sc, p);
  1194. }
  1195. }
  1196. }
  1197. }
  1198. return done_something;
  1199. }
  1200. static int forcing_chain_dup_cmp(const void *av, const void *bv, void *ctx)
  1201. {
  1202. struct solver_scratch *sc = (struct solver_scratch *)ctx;
  1203. int a = *(const int *)av, b = *(const int *)bv;
  1204. int ac, bc;
  1205. ac = sc->pc_scratch[a];
  1206. bc = sc->pc_scratch[b];
  1207. if (ac != bc) return ac > bc ? +1 : -1;
  1208. ac = sc->placements[a].domino->index;
  1209. bc = sc->placements[b].domino->index;
  1210. if (ac != bc) return ac > bc ? +1 : -1;
  1211. return 0;
  1212. }
  1213. static int forcing_chain_sq_cmp(const void *av, const void *bv, void *ctx)
  1214. {
  1215. struct solver_scratch *sc = (struct solver_scratch *)ctx;
  1216. int a = *(const int *)av, b = *(const int *)bv;
  1217. int ac, bc;
  1218. ac = sc->placements[a].domino->index;
  1219. bc = sc->placements[b].domino->index;
  1220. if (ac != bc) return ac > bc ? +1 : -1;
  1221. ac = sc->pc_scratch[a];
  1222. bc = sc->pc_scratch[b];
  1223. if (ac != bc) return ac > bc ? +1 : -1;
  1224. return 0;
  1225. }
  1226. static bool deduce_forcing_chain(struct solver_scratch *sc)
  1227. {
  1228. int si, pi, di, j, k, m;
  1229. bool done_something = false;
  1230. if (!sc->wh_scratch)
  1231. sc->wh_scratch = snewn(sc->wh, int);
  1232. if (!sc->pc_scratch)
  1233. sc->pc_scratch = snewn(sc->pc, int);
  1234. if (!sc->pc_scratch2)
  1235. sc->pc_scratch2 = snewn(sc->pc, int);
  1236. if (!sc->dc_scratch)
  1237. sc->dc_scratch = snewn(sc->dc, int);
  1238. if (!sc->dsf_scratch)
  1239. sc->dsf_scratch = dsf_new_flip(sc->pc);
  1240. /*
  1241. * Start by identifying chains of placements which must all occur
  1242. * together if any of them occurs. We do this by making
  1243. * dsf_scratch a flip dsf binding the placements into an equivalence
  1244. * class for each entire forcing chain, with the two possible sets
  1245. * of dominoes for the chain listed as inverses.
  1246. */
  1247. dsf_reinit(sc->dsf_scratch);
  1248. for (si = 0; si < sc->wh; si++) {
  1249. struct solver_square *sq = &sc->squares[si];
  1250. if (sq->nplacements == 2)
  1251. dsf_merge_flip(sc->dsf_scratch,
  1252. sq->placements[0]->index,
  1253. sq->placements[1]->index, true);
  1254. }
  1255. /*
  1256. * Now read out the whole dsf into pc_scratch, flattening its
  1257. * structured data into a simple integer id per chain of dominoes
  1258. * that must occur together.
  1259. *
  1260. * The integer ids have the property that any two that differ only
  1261. * in the lowest bit (i.e. of the form {2n,2n+1}) represent
  1262. * complementary chains, each of which rules out the other.
  1263. */
  1264. for (pi = 0; pi < sc->pc; pi++) {
  1265. bool inv;
  1266. int c = dsf_canonify_flip(sc->dsf_scratch, pi, &inv);
  1267. sc->pc_scratch[pi] = c * 2 + (inv ? 1 : 0);
  1268. }
  1269. /*
  1270. * Identify chains that contain a duplicate domino, and rule them
  1271. * out. We do this by making a list of the placement indices in
  1272. * pc_scratch2, sorted by (chain id, domino id), so that dupes
  1273. * become adjacent.
  1274. */
  1275. for (pi = 0; pi < sc->pc; pi++)
  1276. sc->pc_scratch2[pi] = pi;
  1277. arraysort(sc->pc_scratch2, sc->pc, forcing_chain_dup_cmp, sc);
  1278. for (j = 0; j < sc->pc ;) {
  1279. struct solver_domino *duplicated_domino = NULL;
  1280. /*
  1281. * This loop iterates once per contiguous segment of the same
  1282. * value in pc_scratch2, i.e. once per chain.
  1283. */
  1284. int ci = sc->pc_scratch[sc->pc_scratch2[j]];
  1285. int climit, cstart = j;
  1286. while (j < sc->pc && sc->pc_scratch[sc->pc_scratch2[j]] == ci)
  1287. j++;
  1288. climit = j;
  1289. /*
  1290. * Now look for a duplicate domino within that chain.
  1291. */
  1292. for (k = cstart; k + 1 < climit; k++) {
  1293. struct solver_placement *p = &sc->placements[sc->pc_scratch2[k]];
  1294. struct solver_placement *q = &sc->placements[sc->pc_scratch2[k+1]];
  1295. if (p->domino == q->domino) {
  1296. duplicated_domino = p->domino;
  1297. break;
  1298. }
  1299. }
  1300. if (!duplicated_domino)
  1301. continue;
  1302. #ifdef SOLVER_DIAGNOSTICS
  1303. if (solver_diagnostics) {
  1304. printf("domino %s occurs more than once in forced chain:",
  1305. duplicated_domino->name);
  1306. for (k = cstart; k < climit; k++)
  1307. printf(" %s", sc->placements[sc->pc_scratch2[k]].name);
  1308. printf("\n");
  1309. }
  1310. #endif
  1311. for (k = cstart; k < climit; k++)
  1312. rule_out_placement(sc, &sc->placements[sc->pc_scratch2[k]]);
  1313. done_something = true;
  1314. }
  1315. if (done_something)
  1316. return true;
  1317. /*
  1318. * A second way in which a whole forcing chain can be ruled out is
  1319. * if it contains all the dominoes that can occupy some other
  1320. * square, so that if the domnioes in the chain were all laid, the
  1321. * other square would be left without any choices.
  1322. *
  1323. * To detect this, we sort the placements again, this time by
  1324. * (domino index, chain index), so that we can easily find a
  1325. * sorted list of chains per domino. That allows us to iterate
  1326. * over the squares and check for a chain id common to all the
  1327. * placements of that square.
  1328. */
  1329. for (pi = 0; pi < sc->pc; pi++)
  1330. sc->pc_scratch2[pi] = pi;
  1331. arraysort(sc->pc_scratch2, sc->pc, forcing_chain_sq_cmp, sc);
  1332. /* Store a lookup table of the first entry in pc_scratch2
  1333. * corresponding to each domino. */
  1334. for (di = j = 0; j < sc->pc; j++) {
  1335. while (di <= sc->placements[sc->pc_scratch2[j]].domino->index) {
  1336. assert(di < sc->dc);
  1337. sc->dc_scratch[di++] = j;
  1338. }
  1339. }
  1340. assert(di == sc->dc);
  1341. for (si = 0; si < sc->wh; si++) {
  1342. struct solver_square *sq = &sc->squares[si];
  1343. int listpos = 0, listsize = 0, listout = 0;
  1344. int exclude[4];
  1345. int n_exclude;
  1346. if (sq->nplacements < 2)
  1347. continue; /* too simple to be worth trying */
  1348. /*
  1349. * Start by checking for chains this square can actually form
  1350. * part of. We won't consider those. (The aim is to find a
  1351. * completely _different_ square whose placements are all
  1352. * ruled out by a chain.)
  1353. */
  1354. assert(sq->nplacements <= lenof(exclude));
  1355. for (j = n_exclude = 0; j < sq->nplacements; j++)
  1356. exclude[n_exclude++] = sc->pc_scratch[sq->placements[j]->index];
  1357. for (j = 0; j < sq->nplacements; j++) {
  1358. struct solver_domino *d = sq->placements[j]->domino;
  1359. listout = listpos = 0;
  1360. for (k = sc->dc_scratch[d->index];
  1361. k < sc->pc && sc->placements[sc->pc_scratch2[k]].domino == d;
  1362. k++) {
  1363. int chain = sc->pc_scratch[sc->pc_scratch2[k]];
  1364. bool keep;
  1365. if (!sc->placements[sc->pc_scratch2[k]].active)
  1366. continue;
  1367. if (j == 0) {
  1368. keep = true;
  1369. } else {
  1370. while (listpos < listsize &&
  1371. sc->wh_scratch[listpos] < chain)
  1372. listpos++;
  1373. keep = (listpos < listsize &&
  1374. sc->wh_scratch[listpos] == chain);
  1375. }
  1376. for (m = 0; m < n_exclude; m++)
  1377. if (chain == exclude[m])
  1378. keep = false;
  1379. if (keep)
  1380. sc->wh_scratch[listout++] = chain;
  1381. }
  1382. listsize = listout;
  1383. if (listsize == 0)
  1384. break; /* ruled out all chains; terminate loop early */
  1385. }
  1386. for (listpos = 0; listpos < listsize; listpos++) {
  1387. int chain = sc->wh_scratch[listpos];
  1388. /*
  1389. * We've found a chain we can rule out.
  1390. */
  1391. #ifdef SOLVER_DIAGNOSTICS
  1392. if (solver_diagnostics) {
  1393. printf("all choices for square %s would be ruled out "
  1394. "by forced chain:", sq->name);
  1395. for (pi = 0; pi < sc->pc; pi++)
  1396. if (sc->pc_scratch[pi] == chain)
  1397. printf(" %s", sc->placements[pi].name);
  1398. printf("\n");
  1399. }
  1400. #endif
  1401. for (pi = 0; pi < sc->pc; pi++)
  1402. if (sc->pc_scratch[pi] == chain)
  1403. rule_out_placement(sc, &sc->placements[pi]);
  1404. done_something = true;
  1405. }
  1406. }
  1407. /*
  1408. * Another thing you can do with forcing chains, besides ruling
  1409. * out a whole one at a time, is to look at each pair of chains
  1410. * that overlap each other. Each such pair gives you two sets of
  1411. * domino placements, such that if either set is not placed, then
  1412. * the other one must be.
  1413. *
  1414. * This means that any domino which has a placement in _both_
  1415. * chains of a pair must occupy one of those two placements, i.e.
  1416. * we can rule that domino out anywhere else it might appear.
  1417. */
  1418. for (di = 0; di < sc->dc; di++) {
  1419. struct solver_domino *d = &sc->dominoes[di];
  1420. if (d->nplacements <= 2)
  1421. continue; /* not enough placements to rule one out */
  1422. for (j = 0; j+1 < d->nplacements; j++) {
  1423. int ij = d->placements[j]->index;
  1424. int cj = sc->pc_scratch[ij];
  1425. for (k = j+1; k < d->nplacements; k++) {
  1426. int ik = d->placements[k]->index;
  1427. int ck = sc->pc_scratch[ik];
  1428. if ((cj ^ ck) == 1) {
  1429. /*
  1430. * Placements j,k of domino d are in complementary
  1431. * chains, so we can rule out all the others.
  1432. */
  1433. int i;
  1434. #ifdef SOLVER_DIAGNOSTICS
  1435. if (solver_diagnostics) {
  1436. printf("domino %s occurs in both complementary "
  1437. "forced chains:", d->name);
  1438. for (i = 0; i < sc->pc; i++)
  1439. if (sc->pc_scratch[i] == cj)
  1440. printf(" %s", sc->placements[i].name);
  1441. printf(" and");
  1442. for (i = 0; i < sc->pc; i++)
  1443. if (sc->pc_scratch[i] == ck)
  1444. printf(" %s", sc->placements[i].name);
  1445. printf("\n");
  1446. }
  1447. #endif
  1448. for (i = d->nplacements; i-- > 0 ;)
  1449. if (i != j && i != k)
  1450. rule_out_placement(sc, d->placements[i]);
  1451. done_something = true;
  1452. goto done_this_domino;
  1453. }
  1454. }
  1455. }
  1456. done_this_domino:;
  1457. }
  1458. return done_something;
  1459. }
  1460. /*
  1461. * Run the solver until it can't make any more progress.
  1462. *
  1463. * Return value is:
  1464. * 0 = no solution exists (puzzle clues are unsatisfiable)
  1465. * 1 = unique solution found (success!)
  1466. * 2 = multiple possibilities remain (puzzle is ambiguous or solver is not
  1467. * smart enough)
  1468. */
  1469. static int run_solver(struct solver_scratch *sc, int max_diff_allowed)
  1470. {
  1471. int di, si, pi;
  1472. bool done_something;
  1473. #ifdef SOLVER_DIAGNOSTICS
  1474. if (solver_diagnostics) {
  1475. int di, j;
  1476. printf("Initial possible placements:\n");
  1477. for (di = 0; di < sc->dc; di++) {
  1478. struct solver_domino *d = &sc->dominoes[di];
  1479. printf(" %s:", d->name);
  1480. for (j = 0; j < d->nplacements; j++)
  1481. printf(" %s", d->placements[j]->name);
  1482. printf("\n");
  1483. }
  1484. }
  1485. #endif
  1486. do {
  1487. done_something = false;
  1488. for (di = 0; di < sc->dc; di++)
  1489. if (deduce_domino_single_placement(sc, di))
  1490. done_something = true;
  1491. if (done_something) {
  1492. sc->max_diff_used = max(sc->max_diff_used, DIFF_TRIVIAL);
  1493. continue;
  1494. }
  1495. for (si = 0; si < sc->wh; si++)
  1496. if (deduce_square_single_placement(sc, si))
  1497. done_something = true;
  1498. if (done_something) {
  1499. sc->max_diff_used = max(sc->max_diff_used, DIFF_TRIVIAL);
  1500. continue;
  1501. }
  1502. if (max_diff_allowed <= DIFF_TRIVIAL)
  1503. continue;
  1504. for (si = 0; si < sc->wh; si++)
  1505. if (deduce_square_single_domino(sc, si))
  1506. done_something = true;
  1507. if (done_something) {
  1508. sc->max_diff_used = max(sc->max_diff_used, DIFF_BASIC);
  1509. continue;
  1510. }
  1511. for (di = 0; di < sc->dc; di++)
  1512. if (deduce_domino_must_overlap(sc, di))
  1513. done_something = true;
  1514. if (done_something) {
  1515. sc->max_diff_used = max(sc->max_diff_used, DIFF_BASIC);
  1516. continue;
  1517. }
  1518. for (pi = 0; pi < sc->pc; pi++)
  1519. if (deduce_local_duplicate(sc, pi))
  1520. done_something = true;
  1521. if (done_something) {
  1522. sc->max_diff_used = max(sc->max_diff_used, DIFF_BASIC);
  1523. continue;
  1524. }
  1525. for (pi = 0; pi < sc->pc; pi++)
  1526. if (deduce_local_duplicate_2(sc, pi))
  1527. done_something = true;
  1528. if (done_something) {
  1529. sc->max_diff_used = max(sc->max_diff_used, DIFF_BASIC);
  1530. continue;
  1531. }
  1532. if (deduce_parity(sc))
  1533. done_something = true;
  1534. if (done_something) {
  1535. sc->max_diff_used = max(sc->max_diff_used, DIFF_BASIC);
  1536. continue;
  1537. }
  1538. if (max_diff_allowed <= DIFF_BASIC)
  1539. continue;
  1540. if (deduce_set(sc, false))
  1541. done_something = true;
  1542. if (done_something) {
  1543. sc->max_diff_used = max(sc->max_diff_used, DIFF_HARD);
  1544. continue;
  1545. }
  1546. if (max_diff_allowed <= DIFF_HARD)
  1547. continue;
  1548. if (deduce_set(sc, true))
  1549. done_something = true;
  1550. if (done_something) {
  1551. sc->max_diff_used = max(sc->max_diff_used, DIFF_EXTREME);
  1552. continue;
  1553. }
  1554. if (deduce_forcing_chain(sc))
  1555. done_something = true;
  1556. if (done_something) {
  1557. sc->max_diff_used = max(sc->max_diff_used, DIFF_EXTREME);
  1558. continue;
  1559. }
  1560. } while (done_something);
  1561. #ifdef SOLVER_DIAGNOSTICS
  1562. if (solver_diagnostics) {
  1563. int di, j;
  1564. printf("Final possible placements:\n");
  1565. for (di = 0; di < sc->dc; di++) {
  1566. struct solver_domino *d = &sc->dominoes[di];
  1567. printf(" %s:", d->name);
  1568. for (j = 0; j < d->nplacements; j++)
  1569. printf(" %s", d->placements[j]->name);
  1570. printf("\n");
  1571. }
  1572. }
  1573. #endif
  1574. for (di = 0; di < sc->dc; di++)
  1575. if (sc->dominoes[di].nplacements == 0)
  1576. return 0;
  1577. for (di = 0; di < sc->dc; di++)
  1578. if (sc->dominoes[di].nplacements > 1)
  1579. return 2;
  1580. return 1;
  1581. }
  1582. /* ----------------------------------------------------------------------
  1583. * Functions for generating a candidate puzzle (before we run the
  1584. * solver to check it's soluble at the right difficulty level).
  1585. */
  1586. struct alloc_val;
  1587. struct alloc_loc;
  1588. struct alloc_scratch {
  1589. /* Game parameters. */
  1590. int n, w, h, wh, dc;
  1591. /* The domino layout. Indexed by squares in the usual y*w+x raster
  1592. * order: layout[i] gives the index of the other square in the
  1593. * same domino as square i. */
  1594. int *layout;
  1595. /* The output array, containing a number in every square. */
  1596. int *numbers;
  1597. /* List of domino values (i.e. number pairs), indexed by DINDEX. */
  1598. struct alloc_val *vals;
  1599. /* List of domino locations, indexed arbitrarily. */
  1600. struct alloc_loc *locs;
  1601. /* Preallocated scratch spaces. */
  1602. int *wh_scratch; /* size wh */
  1603. int *wh2_scratch; /* size 2*wh */
  1604. };
  1605. struct alloc_val {
  1606. int lo, hi;
  1607. bool confounder;
  1608. };
  1609. struct alloc_loc {
  1610. int sq[2];
  1611. };
  1612. static struct alloc_scratch *alloc_make_scratch(int n)
  1613. {
  1614. struct alloc_scratch *as = snew(struct alloc_scratch);
  1615. int lo, hi;
  1616. as->n = n;
  1617. as->w = n+2;
  1618. as->h = n+1;
  1619. as->wh = as->w * as->h;
  1620. as->dc = DCOUNT(n);
  1621. as->layout = snewn(as->wh, int);
  1622. as->numbers = snewn(as->wh, int);
  1623. as->vals = snewn(as->dc, struct alloc_val);
  1624. as->locs = snewn(as->dc, struct alloc_loc);
  1625. as->wh_scratch = snewn(as->wh, int);
  1626. as->wh2_scratch = snewn(as->wh * 2, int);
  1627. for (hi = 0; hi <= n; hi++)
  1628. for (lo = 0; lo <= hi; lo++) {
  1629. struct alloc_val *v = &as->vals[DINDEX(hi, lo)];
  1630. v->lo = lo;
  1631. v->hi = hi;
  1632. }
  1633. return as;
  1634. }
  1635. static void alloc_free_scratch(struct alloc_scratch *as)
  1636. {
  1637. sfree(as->layout);
  1638. sfree(as->numbers);
  1639. sfree(as->vals);
  1640. sfree(as->locs);
  1641. sfree(as->wh_scratch);
  1642. sfree(as->wh2_scratch);
  1643. sfree(as);
  1644. }
  1645. static void alloc_make_layout(struct alloc_scratch *as, random_state *rs)
  1646. {
  1647. int i, pos;
  1648. domino_layout_prealloc(as->w, as->h, rs,
  1649. as->layout, as->wh_scratch, as->wh2_scratch);
  1650. for (i = pos = 0; i < as->wh; i++) {
  1651. if (as->layout[i] > i) {
  1652. struct alloc_loc *loc;
  1653. assert(pos < as->dc);
  1654. loc = &as->locs[pos++];
  1655. loc->sq[0] = i;
  1656. loc->sq[1] = as->layout[i];
  1657. }
  1658. }
  1659. assert(pos == as->dc);
  1660. }
  1661. static void alloc_trivial(struct alloc_scratch *as, random_state *rs)
  1662. {
  1663. int i;
  1664. for (i = 0; i < as->dc; i++)
  1665. as->wh_scratch[i] = i;
  1666. shuffle(as->wh_scratch, as->dc, sizeof(*as->wh_scratch), rs);
  1667. for (i = 0; i < as->dc; i++) {
  1668. struct alloc_val *val = &as->vals[as->wh_scratch[i]];
  1669. struct alloc_loc *loc = &as->locs[i];
  1670. int which_lo = random_upto(rs, 2), which_hi = 1 - which_lo;
  1671. as->numbers[loc->sq[which_lo]] = val->lo;
  1672. as->numbers[loc->sq[which_hi]] = val->hi;
  1673. }
  1674. }
  1675. /*
  1676. * Given a domino location in the form of two square indices, compute
  1677. * the square indices of the domino location that would lie on one
  1678. * side of it. Returns false if the location would be outside the
  1679. * grid, or if it isn't actually a domino in the layout.
  1680. */
  1681. static bool alloc_find_neighbour(
  1682. struct alloc_scratch *as, int p0, int p1, int *n0, int *n1)
  1683. {
  1684. int x0 = p0 % as->w, y0 = p0 / as->w, x1 = p1 % as->w, y1 = p1 / as->w;
  1685. int dy = y1-y0, dx = x1-x0;
  1686. int nx0 = x0 + dy, ny0 = y0 - dx, nx1 = x1 + dy, ny1 = y1 - dx;
  1687. int np0, np1;
  1688. if (!(nx0 >= 0 && nx0 < as->w && ny0 >= 0 && ny0 < as->h &&
  1689. nx1 >= 1 && nx1 < as->w && ny1 >= 1 && ny1 < as->h))
  1690. return false; /* out of bounds */
  1691. np0 = ny0 * as->w + nx0;
  1692. np1 = ny1 * as->w + nx1;
  1693. if (as->layout[np0] != np1)
  1694. return false; /* not a domino */
  1695. *n0 = np0;
  1696. *n1 = np1;
  1697. return true;
  1698. }
  1699. static bool alloc_try_unique(struct alloc_scratch *as, random_state *rs)
  1700. {
  1701. int i;
  1702. for (i = 0; i < as->dc; i++)
  1703. as->wh_scratch[i] = i;
  1704. shuffle(as->wh_scratch, as->dc, sizeof(*as->wh_scratch), rs);
  1705. for (i = 0; i < as->dc; i++)
  1706. as->wh2_scratch[i] = i;
  1707. shuffle(as->wh2_scratch, as->dc, sizeof(*as->wh2_scratch), rs);
  1708. for (i = 0; i < as->wh; i++)
  1709. as->numbers[i] = -1;
  1710. for (i = 0; i < as->dc; i++) {
  1711. struct alloc_val *val = &as->vals[as->wh_scratch[i]];
  1712. struct alloc_loc *loc = &as->locs[as->wh2_scratch[i]];
  1713. int which_lo, which_hi;
  1714. bool can_lo_0 = true, can_lo_1 = true;
  1715. int n0, n1;
  1716. /*
  1717. * This is basically the same strategy as alloc_trivial:
  1718. * simply iterate through the locations and values in random
  1719. * relative order and pair them up. But we make sure to avoid
  1720. * the most common, and also simplest, cause of a non-unique
  1721. * solution:two dominoes side by side, sharing a number at
  1722. * opposite ends. Any section of that form automatically leads
  1723. * to an alternative solution:
  1724. *
  1725. * +-------+ +---+---+
  1726. * | 1 2 | | 1 | 2 |
  1727. * +-------+ <-> | | |
  1728. * | 2 3 | | 2 | 3 |
  1729. * +-------+ +---+---+
  1730. *
  1731. * So as we place each domino, we check for a neighbouring
  1732. * domino on each side, and if there is one, rule out any
  1733. * placement of _this_ domino that places a number diagonally
  1734. * opposite the same number in the neighbour.
  1735. *
  1736. * Sometimes this can fail completely, if a domino on each
  1737. * side is already placed and between them they rule out all
  1738. * placements of this one. But it happens rarely enough that
  1739. * it's fine to just abort and try the layout again.
  1740. */
  1741. if (alloc_find_neighbour(as, loc->sq[0], loc->sq[1], &n0, &n1) &&
  1742. (as->numbers[n0] == val->hi || as->numbers[n1] == val->lo))
  1743. can_lo_0 = false;
  1744. if (alloc_find_neighbour(as, loc->sq[1], loc->sq[0], &n0, &n1) &&
  1745. (as->numbers[n0] == val->hi || as->numbers[n1] == val->lo))
  1746. can_lo_1 = false;
  1747. if (!can_lo_0 && !can_lo_1)
  1748. return false; /* layout failed */
  1749. else if (can_lo_0 && can_lo_1)
  1750. which_lo = random_upto(rs, 2);
  1751. else
  1752. which_lo = can_lo_0 ? 0 : 1;
  1753. which_hi = 1 - which_lo;
  1754. as->numbers[loc->sq[which_lo]] = val->lo;
  1755. as->numbers[loc->sq[which_hi]] = val->hi;
  1756. }
  1757. return true;
  1758. }
  1759. static bool alloc_try_hard(struct alloc_scratch *as, random_state *rs)
  1760. {
  1761. int i, x, y, hi, lo, vals, locs, confounders_needed;
  1762. bool ok;
  1763. for (i = 0; i < as->wh; i++)
  1764. as->numbers[i] = -1;
  1765. /*
  1766. * Shuffle the location indices.
  1767. */
  1768. for (i = 0; i < as->dc; i++)
  1769. as->wh2_scratch[i] = i;
  1770. shuffle(as->wh2_scratch, as->dc, sizeof(*as->wh2_scratch), rs);
  1771. /*
  1772. * Start by randomly placing the double dominoes, to give a
  1773. * starting instance of every number to try to put other things
  1774. * next to.
  1775. */
  1776. for (i = 0; i <= as->n; i++)
  1777. as->wh_scratch[i] = DINDEX(i, i);
  1778. shuffle(as->wh_scratch, i, sizeof(*as->wh_scratch), rs);
  1779. for (i = 0; i <= as->n; i++) {
  1780. struct alloc_loc *loc = &as->locs[as->wh2_scratch[i]];
  1781. as->numbers[loc->sq[0]] = as->numbers[loc->sq[1]] = i;
  1782. }
  1783. /*
  1784. * Find all the dominoes that don't yet have a _wrong_ placement
  1785. * somewhere in the grid.
  1786. */
  1787. for (i = 0; i < as->dc; i++)
  1788. as->vals[i].confounder = false;
  1789. for (y = 0; y < as->h; y++) {
  1790. for (x = 0; x < as->w; x++) {
  1791. int p = y * as->w + x;
  1792. if (as->numbers[p] == -1)
  1793. continue;
  1794. if (x+1 < as->w) {
  1795. int p1 = y * as->w + (x+1);
  1796. if (as->layout[p] != p1 && as->numbers[p1] != -1)
  1797. as->vals[DINDEX(as->numbers[p], as->numbers[p1])]
  1798. .confounder = true;
  1799. }
  1800. if (y+1 < as->h) {
  1801. int p1 = (y+1) * as->w + x;
  1802. if (as->layout[p] != p1 && as->numbers[p1] != -1)
  1803. as->vals[DINDEX(as->numbers[p], as->numbers[p1])]
  1804. .confounder = true;
  1805. }
  1806. }
  1807. }
  1808. for (i = confounders_needed = 0; i < as->dc; i++)
  1809. if (!as->vals[i].confounder)
  1810. confounders_needed++;
  1811. /*
  1812. * Make a shuffled list of all the unplaced dominoes, and go
  1813. * through it trying to find a placement for each one that also
  1814. * fills in at least one of the needed confounders.
  1815. */
  1816. vals = 0;
  1817. for (hi = 0; hi <= as->n; hi++)
  1818. for (lo = 0; lo < hi; lo++)
  1819. as->wh_scratch[vals++] = DINDEX(hi, lo);
  1820. shuffle(as->wh_scratch, vals, sizeof(*as->wh_scratch), rs);
  1821. locs = as->dc;
  1822. while (vals > 0) {
  1823. int valpos, valout, oldvals = vals;
  1824. for (valpos = valout = 0; valpos < vals; valpos++) {
  1825. int validx = as->wh_scratch[valpos];
  1826. struct alloc_val *val = &as->vals[validx];
  1827. struct alloc_loc *loc;
  1828. int locpos, si, which_lo;
  1829. for (locpos = 0; locpos < locs; locpos++) {
  1830. int locidx = as->wh2_scratch[locpos];
  1831. int wi, flip;
  1832. loc = &as->locs[locidx];
  1833. if (as->numbers[loc->sq[0]] != -1)
  1834. continue; /* this location is already filled */
  1835. flip = random_upto(rs, 2);
  1836. /* Try this location both ways round. */
  1837. for (wi = 0; wi < 2; wi++) {
  1838. int n0, n1;
  1839. which_lo = wi ^ flip;
  1840. /* First, do the same check as in alloc_try_unique, to
  1841. * avoid making an obviously insoluble puzzle. */
  1842. if (alloc_find_neighbour(as, loc->sq[which_lo],
  1843. loc->sq[1-which_lo], &n0, &n1) &&
  1844. (as->numbers[n0] == val->hi ||
  1845. as->numbers[n1] == val->lo))
  1846. break; /* can't place it this way round */
  1847. if (confounders_needed == 0)
  1848. goto place_ok;
  1849. /* Look to see if we're adding at least one
  1850. * previously absent confounder. */
  1851. for (si = 0; si < 2; si++) {
  1852. int x = loc->sq[si] % as->w, y = loc->sq[si] / as->w;
  1853. int n = (si == which_lo ? val->lo : val->hi);
  1854. int d;
  1855. for (d = 0; d < 4; d++) {
  1856. int dx = d==0 ? +1 : d==2 ? -1 : 0;
  1857. int dy = d==1 ? +1 : d==3 ? -1 : 0;
  1858. int x1 = x+dx, y1 = y+dy, p1 = y1 * as->w + x1;
  1859. if (x1 >= 0 && x1 < as->w &&
  1860. y1 >= 0 && y1 < as->h &&
  1861. as->numbers[p1] != -1 &&
  1862. !(as->vals[DINDEX(n, as->numbers[p1])]
  1863. .confounder)) {
  1864. /*
  1865. * Place this domino.
  1866. */
  1867. goto place_ok;
  1868. }
  1869. }
  1870. }
  1871. }
  1872. }
  1873. /* If we get here without executing 'goto place_ok', we
  1874. * didn't find anywhere useful to put this domino. Put it
  1875. * back on the list for the next pass. */
  1876. as->wh_scratch[valout++] = validx;
  1877. continue;
  1878. place_ok:;
  1879. /* We've found a domino to place. Place it, and fill in
  1880. * all the confounders it adds. */
  1881. as->numbers[loc->sq[which_lo]] = val->lo;
  1882. as->numbers[loc->sq[1 - which_lo]] = val->hi;
  1883. for (si = 0; si < 2; si++) {
  1884. int p = loc->sq[si];
  1885. int n = as->numbers[p];
  1886. int x = p % as->w, y = p / as->w;
  1887. int d;
  1888. for (d = 0; d < 4; d++) {
  1889. int dx = d==0 ? +1 : d==2 ? -1 : 0;
  1890. int dy = d==1 ? +1 : d==3 ? -1 : 0;
  1891. int x1 = x+dx, y1 = y+dy, p1 = y1 * as->w + x1;
  1892. if (x1 >= 0 && x1 < as->w && y1 >= 0 && y1 < as->h &&
  1893. p1 != loc->sq[1-si] && as->numbers[p1] != -1) {
  1894. int di = DINDEX(n, as->numbers[p1]);
  1895. if (!as->vals[di].confounder)
  1896. confounders_needed--;
  1897. as->vals[di].confounder = true;
  1898. }
  1899. }
  1900. }
  1901. }
  1902. vals = valout;
  1903. if (oldvals == vals)
  1904. break;
  1905. }
  1906. ok = true;
  1907. for (i = 0; i < as->dc; i++)
  1908. if (!as->vals[i].confounder)
  1909. ok = false;
  1910. for (i = 0; i < as->wh; i++)
  1911. if (as->numbers[i] == -1)
  1912. ok = false;
  1913. return ok;
  1914. }
  1915. static char *new_game_desc(const game_params *params, random_state *rs,
  1916. char **aux, bool interactive)
  1917. {
  1918. int n = params->n, w = n+2, h = n+1, wh = w*h, diff = params->diff;
  1919. struct solver_scratch *sc;
  1920. struct alloc_scratch *as;
  1921. int i, j, k, len;
  1922. char *ret;
  1923. #ifndef OMIT_DIFFICULTY_CAP
  1924. /*
  1925. * Cap the difficulty level for small puzzles which would
  1926. * otherwise become impossible to generate.
  1927. *
  1928. * Under an #ifndef, to make it easy to remove this cap for the
  1929. * purpose of re-testing what it ought to be.
  1930. */
  1931. if (diff != DIFF_AMBIGUOUS) {
  1932. if (n == 1 && diff > DIFF_TRIVIAL)
  1933. diff = DIFF_TRIVIAL;
  1934. if (n == 2 && diff > DIFF_BASIC)
  1935. diff = DIFF_BASIC;
  1936. }
  1937. #endif /* OMIT_DIFFICULTY_CAP */
  1938. /*
  1939. * Allocate space in which to lay the grid out.
  1940. */
  1941. sc = solver_make_scratch(n);
  1942. as = alloc_make_scratch(n);
  1943. /*
  1944. * I haven't been able to think of any particularly clever
  1945. * techniques for generating instances of Dominosa with a
  1946. * unique solution. Many of the deductions used in this puzzle
  1947. * are based on information involving half the grid at a time
  1948. * (`of all the 6s, exactly one is next to a 3'), so a strategy
  1949. * of partially solving the grid and then perturbing the place
  1950. * where the solver got stuck seems particularly likely to
  1951. * accidentally destroy the information which the solver had
  1952. * used in getting that far. (Contrast with, say, Mines, in
  1953. * which most deductions are local so this is an excellent
  1954. * strategy.)
  1955. *
  1956. * Therefore I resort to the basest of brute force methods:
  1957. * generate a random grid, see if it's solvable, throw it away
  1958. * and try again if not. My only concession to sophistication
  1959. * and cleverness is to at least _try_ not to generate obvious
  1960. * 2x2 ambiguous sections (see comment below in the domino-
  1961. * flipping section).
  1962. *
  1963. * During tests performed on 2005-07-15, I found that the brute
  1964. * force approach without that tweak had to throw away about 87
  1965. * grids on average (at the default n=6) before finding a
  1966. * unique one, or a staggering 379 at n=9; good job the
  1967. * generator and solver are fast! When I added the
  1968. * ambiguous-section avoidance, those numbers came down to 19
  1969. * and 26 respectively, which is a lot more sensible.
  1970. */
  1971. while (1) {
  1972. alloc_make_layout(as, rs);
  1973. if (diff == DIFF_AMBIGUOUS) {
  1974. /* Just assign numbers to each domino completely at random. */
  1975. alloc_trivial(as, rs);
  1976. } else if (diff < DIFF_HARD) {
  1977. /* Try to rule out the most common case of a non-unique solution */
  1978. if (!alloc_try_unique(as, rs))
  1979. continue;
  1980. } else {
  1981. /*
  1982. * For Hard puzzles and above, we'd like there not to be
  1983. * any easy toehold to start with.
  1984. *
  1985. * Mostly, that's arranged by alloc_try_hard, which will
  1986. * ensure that no domino starts off with only one
  1987. * potential placement. But a few other deductions
  1988. * possible at Basic level can still sneak through the
  1989. * cracks - for example, if the only two placements of one
  1990. * domino overlap in a square, and you therefore rule out
  1991. * some other domino that can use that square, you might
  1992. * then find that _that_ domino now has only one
  1993. * placement, and you've made a start.
  1994. *
  1995. * Of course, the main difficulty-level check will still
  1996. * guarantee that you have to do a harder deduction
  1997. * _somewhere_ in the grid. But it's more elegant if
  1998. * there's nowhere obvious to get started at all.
  1999. */
  2000. int di;
  2001. bool ok;
  2002. if (!alloc_try_hard(as, rs))
  2003. continue;
  2004. solver_setup_grid(sc, as->numbers);
  2005. if (run_solver(sc, DIFF_BASIC) < 2)
  2006. continue;
  2007. ok = true;
  2008. for (di = 0; di < sc->dc; di++)
  2009. if (sc->dominoes[di].nplacements <= 1) {
  2010. ok = false;
  2011. break;
  2012. }
  2013. if (!ok) {
  2014. continue;
  2015. }
  2016. }
  2017. if (diff != DIFF_AMBIGUOUS) {
  2018. int solver_result;
  2019. solver_setup_grid(sc, as->numbers);
  2020. solver_result = run_solver(sc, diff);
  2021. if (solver_result > 1)
  2022. continue; /* puzzle couldn't be solved at this difficulty */
  2023. if (sc->max_diff_used < diff)
  2024. continue; /* puzzle _could_ be solved at easier difficulty */
  2025. }
  2026. break;
  2027. }
  2028. #ifdef GENERATION_DIAGNOSTICS
  2029. for (j = 0; j < h; j++) {
  2030. for (i = 0; i < w; i++) {
  2031. putchar('0' + as->numbers[j*w+i]);
  2032. }
  2033. putchar('\n');
  2034. }
  2035. putchar('\n');
  2036. #endif
  2037. /*
  2038. * Encode the resulting game state.
  2039. *
  2040. * Our encoding is a string of digits. Any number greater than
  2041. * 9 is represented by a decimal integer within square
  2042. * brackets. We know there are n+2 of every number (it's paired
  2043. * with each number from 0 to n inclusive, and one of those is
  2044. * itself so that adds another occurrence), so we can work out
  2045. * the string length in advance.
  2046. */
  2047. /*
  2048. * To work out the total length of the decimal encodings of all
  2049. * the numbers from 0 to n inclusive:
  2050. * - every number has a units digit; total is n+1.
  2051. * - all numbers above 9 have a tens digit; total is max(n+1-10,0).
  2052. * - all numbers above 99 have a hundreds digit; total is max(n+1-100,0).
  2053. * - and so on.
  2054. */
  2055. len = n+1;
  2056. for (i = 10; i <= n; i *= 10)
  2057. len += max(n + 1 - i, 0);
  2058. /* Now add two square brackets for each number above 9. */
  2059. len += 2 * max(n + 1 - 10, 0);
  2060. /* And multiply by n+2 for the repeated occurrences of each number. */
  2061. len *= n+2;
  2062. /*
  2063. * Now actually encode the string.
  2064. */
  2065. ret = snewn(len+1, char);
  2066. j = 0;
  2067. for (i = 0; i < wh; i++) {
  2068. k = as->numbers[i];
  2069. if (k < 10)
  2070. ret[j++] = '0' + k;
  2071. else
  2072. j += sprintf(ret+j, "[%d]", k);
  2073. assert(j <= len);
  2074. }
  2075. assert(j == len);
  2076. ret[j] = '\0';
  2077. /*
  2078. * Encode the solved state as an aux_info.
  2079. */
  2080. {
  2081. char *auxinfo = snewn(wh+1, char);
  2082. for (i = 0; i < wh; i++) {
  2083. int v = as->layout[i];
  2084. auxinfo[i] = (v == i+1 ? 'L' : v == i-1 ? 'R' :
  2085. v == i+w ? 'T' : v == i-w ? 'B' : '.');
  2086. }
  2087. auxinfo[wh] = '\0';
  2088. *aux = auxinfo;
  2089. }
  2090. solver_free_scratch(sc);
  2091. alloc_free_scratch(as);
  2092. return ret;
  2093. }
  2094. static const char *validate_desc(const game_params *params, const char *desc)
  2095. {
  2096. int n = params->n, w = n+2, h = n+1, wh = w*h;
  2097. int *occurrences;
  2098. int i, j;
  2099. const char *ret;
  2100. ret = NULL;
  2101. occurrences = snewn(n+1, int);
  2102. for (i = 0; i <= n; i++)
  2103. occurrences[i] = 0;
  2104. for (i = 0; i < wh; i++) {
  2105. if (!*desc) {
  2106. ret = ret ? ret : "Game description is too short";
  2107. } else {
  2108. if (*desc >= '0' && *desc <= '9')
  2109. j = *desc++ - '0';
  2110. else if (*desc == '[') {
  2111. desc++;
  2112. j = atoi(desc);
  2113. while (*desc && isdigit((unsigned char)*desc)) desc++;
  2114. if (*desc != ']')
  2115. ret = ret ? ret : "Missing ']' in game description";
  2116. else
  2117. desc++;
  2118. } else {
  2119. j = -1;
  2120. ret = ret ? ret : "Invalid syntax in game description";
  2121. }
  2122. if (j < 0 || j > n)
  2123. ret = ret ? ret : "Number out of range in game description";
  2124. else
  2125. occurrences[j]++;
  2126. }
  2127. }
  2128. if (*desc)
  2129. ret = ret ? ret : "Game description is too long";
  2130. if (!ret) {
  2131. for (i = 0; i <= n; i++)
  2132. if (occurrences[i] != n+2)
  2133. ret = "Incorrect number balance in game description";
  2134. }
  2135. sfree(occurrences);
  2136. return ret;
  2137. }
  2138. static game_state *new_game(midend *me, const game_params *params,
  2139. const char *desc)
  2140. {
  2141. int n = params->n, w = n+2, h = n+1, wh = w*h;
  2142. game_state *state = snew(game_state);
  2143. int i, j;
  2144. state->params = *params;
  2145. state->w = w;
  2146. state->h = h;
  2147. state->grid = snewn(wh, int);
  2148. for (i = 0; i < wh; i++)
  2149. state->grid[i] = i;
  2150. state->edges = snewn(wh, unsigned short);
  2151. for (i = 0; i < wh; i++)
  2152. state->edges[i] = 0;
  2153. state->numbers = snew(struct game_numbers);
  2154. state->numbers->refcount = 1;
  2155. state->numbers->numbers = snewn(wh, int);
  2156. for (i = 0; i < wh; i++) {
  2157. assert(*desc);
  2158. if (*desc >= '0' && *desc <= '9')
  2159. j = *desc++ - '0';
  2160. else {
  2161. assert(*desc == '[');
  2162. desc++;
  2163. j = atoi(desc);
  2164. while (*desc && isdigit((unsigned char)*desc)) desc++;
  2165. assert(*desc == ']');
  2166. desc++;
  2167. }
  2168. assert(j >= 0 && j <= n);
  2169. state->numbers->numbers[i] = j;
  2170. }
  2171. state->completed = false;
  2172. state->cheated = false;
  2173. return state;
  2174. }
  2175. static game_state *dup_game(const game_state *state)
  2176. {
  2177. int n = state->params.n, w = n+2, h = n+1, wh = w*h;
  2178. game_state *ret = snew(game_state);
  2179. ret->params = state->params;
  2180. ret->w = state->w;
  2181. ret->h = state->h;
  2182. ret->grid = snewn(wh, int);
  2183. memcpy(ret->grid, state->grid, wh * sizeof(int));
  2184. ret->edges = snewn(wh, unsigned short);
  2185. memcpy(ret->edges, state->edges, wh * sizeof(unsigned short));
  2186. ret->numbers = state->numbers;
  2187. ret->numbers->refcount++;
  2188. ret->completed = state->completed;
  2189. ret->cheated = state->cheated;
  2190. return ret;
  2191. }
  2192. static void free_game(game_state *state)
  2193. {
  2194. sfree(state->grid);
  2195. sfree(state->edges);
  2196. if (--state->numbers->refcount <= 0) {
  2197. sfree(state->numbers->numbers);
  2198. sfree(state->numbers);
  2199. }
  2200. sfree(state);
  2201. }
  2202. static char *solution_move_string(struct solver_scratch *sc)
  2203. {
  2204. char *ret;
  2205. int retlen, retsize;
  2206. int i, pass;
  2207. /*
  2208. * First make a pass putting in edges for -1, then make a pass
  2209. * putting in dominoes for +1.
  2210. */
  2211. retsize = 256;
  2212. ret = snewn(retsize, char);
  2213. retlen = sprintf(ret, "S");
  2214. for (pass = 0; pass < 2; pass++) {
  2215. char type = "ED"[pass];
  2216. for (i = 0; i < sc->pc; i++) {
  2217. struct solver_placement *p = &sc->placements[i];
  2218. char buf[80];
  2219. int extra;
  2220. if (pass == 0) {
  2221. /* Emit a barrier if this placement is ruled out for
  2222. * the domino. */
  2223. if (p->active)
  2224. continue;
  2225. } else {
  2226. /* Emit a domino if this placement is the only one not
  2227. * ruled out. */
  2228. if (!p->active || p->domino->nplacements > 1)
  2229. continue;
  2230. }
  2231. extra = sprintf(buf, ";%c%d,%d", type,
  2232. p->squares[0]->index, p->squares[1]->index);
  2233. if (retlen + extra + 1 >= retsize) {
  2234. retsize = retlen + extra + 256;
  2235. ret = sresize(ret, retsize, char);
  2236. }
  2237. strcpy(ret + retlen, buf);
  2238. retlen += extra;
  2239. }
  2240. }
  2241. return ret;
  2242. }
  2243. static char *solve_game(const game_state *state, const game_state *currstate,
  2244. const char *aux, const char **error)
  2245. {
  2246. int n = state->params.n, w = n+2, h = n+1, wh = w*h;
  2247. char *ret;
  2248. int retlen, retsize;
  2249. int i;
  2250. char buf[80];
  2251. int extra;
  2252. if (aux) {
  2253. retsize = 256;
  2254. ret = snewn(retsize, char);
  2255. retlen = sprintf(ret, "S");
  2256. for (i = 0; i < wh; i++) {
  2257. if (aux[i] == 'L')
  2258. extra = sprintf(buf, ";D%d,%d", i, i+1);
  2259. else if (aux[i] == 'T')
  2260. extra = sprintf(buf, ";D%d,%d", i, i+w);
  2261. else
  2262. continue;
  2263. if (retlen + extra + 1 >= retsize) {
  2264. retsize = retlen + extra + 256;
  2265. ret = sresize(ret, retsize, char);
  2266. }
  2267. strcpy(ret + retlen, buf);
  2268. retlen += extra;
  2269. }
  2270. } else {
  2271. struct solver_scratch *sc = solver_make_scratch(n);
  2272. solver_setup_grid(sc, state->numbers->numbers);
  2273. run_solver(sc, DIFFCOUNT);
  2274. ret = solution_move_string(sc);
  2275. solver_free_scratch(sc);
  2276. }
  2277. return ret;
  2278. }
  2279. static bool game_can_format_as_text_now(const game_params *params)
  2280. {
  2281. return params->n < 1000;
  2282. }
  2283. static void draw_domino(char *board, int start, char corner,
  2284. int dshort, int nshort, char cshort,
  2285. int dlong, int nlong, char clong)
  2286. {
  2287. int go_short = nshort*dshort, go_long = nlong*dlong, i;
  2288. board[start] = corner;
  2289. board[start + go_short] = corner;
  2290. board[start + go_long] = corner;
  2291. board[start + go_short + go_long] = corner;
  2292. for (i = 1; i < nshort; ++i) {
  2293. int j = start + i*dshort, k = start + i*dshort + go_long;
  2294. if (board[j] != corner) board[j] = cshort;
  2295. if (board[k] != corner) board[k] = cshort;
  2296. }
  2297. for (i = 1; i < nlong; ++i) {
  2298. int j = start + i*dlong, k = start + i*dlong + go_short;
  2299. if (board[j] != corner) board[j] = clong;
  2300. if (board[k] != corner) board[k] = clong;
  2301. }
  2302. }
  2303. static char *game_text_format(const game_state *state)
  2304. {
  2305. int w = state->w, h = state->h, r, c;
  2306. int cw = 4, ch = 2, gw = cw*w + 2, gh = ch * h + 1, len = gw * gh;
  2307. char *board = snewn(len + 1, char);
  2308. memset(board, ' ', len);
  2309. for (r = 0; r < h; ++r) {
  2310. for (c = 0; c < w; ++c) {
  2311. int cell = r*ch*gw + cw*c, center = cell + gw*ch/2 + cw/2;
  2312. int i = r*w + c, num = state->numbers->numbers[i];
  2313. if (num < 100) {
  2314. board[center] = '0' + num % 10;
  2315. if (num >= 10) board[center - 1] = '0' + num / 10;
  2316. } else {
  2317. board[center+1] = '0' + num % 10;
  2318. board[center] = '0' + num / 10 % 10;
  2319. board[center-1] = '0' + num / 100;
  2320. }
  2321. if (state->edges[i] & EDGE_L) board[center - cw/2] = '|';
  2322. if (state->edges[i] & EDGE_R) board[center + cw/2] = '|';
  2323. if (state->edges[i] & EDGE_T) board[center - gw] = '-';
  2324. if (state->edges[i] & EDGE_B) board[center + gw] = '-';
  2325. if (state->grid[i] == i) continue; /* no domino pairing */
  2326. if (state->grid[i] < i) continue; /* already done */
  2327. assert (state->grid[i] == i + 1 || state->grid[i] == i + w);
  2328. if (state->grid[i] == i + 1)
  2329. draw_domino(board, cell, '+', gw, ch, '|', +1, 2*cw, '-');
  2330. else if (state->grid[i] == i + w)
  2331. draw_domino(board, cell, '+', +1, cw, '-', gw, 2*ch, '|');
  2332. }
  2333. board[r*ch*gw + gw - 1] = '\n';
  2334. board[r*ch*gw + gw + gw - 1] = '\n';
  2335. }
  2336. board[len - 1] = '\n';
  2337. board[len] = '\0';
  2338. return board;
  2339. }
  2340. struct game_ui {
  2341. int cur_x, cur_y, highlight_1, highlight_2;
  2342. bool cur_visible;
  2343. };
  2344. static game_ui *new_ui(const game_state *state)
  2345. {
  2346. game_ui *ui = snew(game_ui);
  2347. ui->cur_x = ui->cur_y = 0;
  2348. ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false);
  2349. ui->highlight_1 = ui->highlight_2 = -1;
  2350. return ui;
  2351. }
  2352. static void free_ui(game_ui *ui)
  2353. {
  2354. sfree(ui);
  2355. }
  2356. static void game_changed_state(game_ui *ui, const game_state *oldstate,
  2357. const game_state *newstate)
  2358. {
  2359. if (!oldstate->completed && newstate->completed)
  2360. ui->cur_visible = false;
  2361. }
  2362. static const char *current_key_label(const game_ui *ui,
  2363. const game_state *state, int button)
  2364. {
  2365. if (IS_CURSOR_SELECT(button)) {
  2366. int d1, d2, w = state->w;
  2367. if (!((ui->cur_x ^ ui->cur_y) & 1))
  2368. return ""; /* must have exactly one dimension odd */
  2369. d1 = (ui->cur_y / 2) * w + (ui->cur_x / 2);
  2370. d2 = ((ui->cur_y+1) / 2) * w + ((ui->cur_x+1) / 2);
  2371. /* We can't mark an edge next to any domino. */
  2372. if (button == CURSOR_SELECT2 &&
  2373. (state->grid[d1] != d1 || state->grid[d2] != d2))
  2374. return "";
  2375. if (button == CURSOR_SELECT) {
  2376. if (state->grid[d1] == d2) return "Remove";
  2377. return "Place";
  2378. } else {
  2379. int edge = d2 == d1 + 1 ? EDGE_R : EDGE_B;
  2380. if (state->edges[d1] & edge) return "Remove";
  2381. return "Line";
  2382. }
  2383. }
  2384. return "";
  2385. }
  2386. #define PREFERRED_TILESIZE 32
  2387. #define TILESIZE (ds->tilesize)
  2388. #define BORDER (TILESIZE * 3 / 4)
  2389. #define DOMINO_GUTTER (TILESIZE / 16)
  2390. #define DOMINO_RADIUS (TILESIZE / 8)
  2391. #define DOMINO_COFFSET (DOMINO_GUTTER + DOMINO_RADIUS)
  2392. #define CURSOR_RADIUS (TILESIZE / 4)
  2393. #define COORD(x) ( (x) * TILESIZE + BORDER )
  2394. #define FROMCOORD(x) ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
  2395. struct game_drawstate {
  2396. int w, h, tilesize;
  2397. unsigned long *visible;
  2398. };
  2399. static char *interpret_move(const game_state *state, game_ui *ui,
  2400. const game_drawstate *ds,
  2401. int x, int y, int button)
  2402. {
  2403. int w = state->w, h = state->h;
  2404. char buf[80];
  2405. /*
  2406. * A left-click between two numbers toggles a domino covering
  2407. * them. A right-click toggles an edge.
  2408. */
  2409. if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
  2410. int tx = FROMCOORD(x), ty = FROMCOORD(y), t = ty*w+tx;
  2411. int dx, dy;
  2412. int d1, d2;
  2413. if (tx < 0 || tx >= w || ty < 0 || ty >= h)
  2414. return MOVE_UNUSED;
  2415. /*
  2416. * Now we know which square the click was in, decide which
  2417. * edge of the square it was closest to.
  2418. */
  2419. dx = 2 * (x - COORD(tx)) - TILESIZE;
  2420. dy = 2 * (y - COORD(ty)) - TILESIZE;
  2421. if (abs(dx) > abs(dy) && dx < 0 && tx > 0)
  2422. d1 = t - 1, d2 = t; /* clicked in right side of domino */
  2423. else if (abs(dx) > abs(dy) && dx > 0 && tx+1 < w)
  2424. d1 = t, d2 = t + 1; /* clicked in left side of domino */
  2425. else if (abs(dy) > abs(dx) && dy < 0 && ty > 0)
  2426. d1 = t - w, d2 = t; /* clicked in bottom half of domino */
  2427. else if (abs(dy) > abs(dx) && dy > 0 && ty+1 < h)
  2428. d1 = t, d2 = t + w; /* clicked in top half of domino */
  2429. else
  2430. return MOVE_NO_EFFECT; /* clicked precisely on a diagonal */
  2431. /*
  2432. * We can't mark an edge next to any domino.
  2433. */
  2434. if (button == RIGHT_BUTTON &&
  2435. (state->grid[d1] != d1 || state->grid[d2] != d2))
  2436. return MOVE_NO_EFFECT;
  2437. ui->cur_visible = false;
  2438. sprintf(buf, "%c%d,%d", (int)(button == RIGHT_BUTTON ? 'E' : 'D'), d1, d2);
  2439. return dupstr(buf);
  2440. } else if (IS_CURSOR_MOVE(button)) {
  2441. ui->cur_visible = true;
  2442. move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, false);
  2443. return MOVE_UI_UPDATE;
  2444. } else if (IS_CURSOR_SELECT(button)) {
  2445. int d1, d2;
  2446. if (!((ui->cur_x ^ ui->cur_y) & 1))
  2447. return MOVE_NO_EFFECT; /* must have exactly one dimension odd */
  2448. d1 = (ui->cur_y / 2) * w + (ui->cur_x / 2);
  2449. d2 = ((ui->cur_y+1) / 2) * w + ((ui->cur_x+1) / 2);
  2450. /*
  2451. * We can't mark an edge next to any domino.
  2452. */
  2453. if (button == CURSOR_SELECT2 &&
  2454. (state->grid[d1] != d1 || state->grid[d2] != d2))
  2455. return MOVE_NO_EFFECT;
  2456. sprintf(buf, "%c%d,%d", (int)(button == CURSOR_SELECT2 ? 'E' : 'D'), d1, d2);
  2457. return dupstr(buf);
  2458. } else if (isdigit(button)) {
  2459. int n = state->params.n, num = button - '0';
  2460. if (num > n) {
  2461. return MOVE_UNUSED;
  2462. } else if (ui->highlight_1 == num) {
  2463. ui->highlight_1 = -1;
  2464. } else if (ui->highlight_2 == num) {
  2465. ui->highlight_2 = -1;
  2466. } else if (ui->highlight_1 == -1) {
  2467. ui->highlight_1 = num;
  2468. } else if (ui->highlight_2 == -1) {
  2469. ui->highlight_2 = num;
  2470. } else {
  2471. return MOVE_NO_EFFECT;
  2472. }
  2473. return MOVE_UI_UPDATE;
  2474. }
  2475. return MOVE_UNUSED;
  2476. }
  2477. static game_state *execute_move(const game_state *state, const char *move)
  2478. {
  2479. int n = state->params.n, w = n+2, h = n+1, wh = w*h;
  2480. int d1, d2, d3, p;
  2481. game_state *ret = dup_game(state);
  2482. while (*move) {
  2483. if (move[0] == 'S') {
  2484. int i;
  2485. ret->cheated = true;
  2486. /*
  2487. * Clear the existing edges and domino placements. We
  2488. * expect the S to be followed by other commands.
  2489. */
  2490. for (i = 0; i < wh; i++) {
  2491. ret->grid[i] = i;
  2492. ret->edges[i] = 0;
  2493. }
  2494. move++;
  2495. } else if (move[0] == 'D' &&
  2496. sscanf(move+1, "%d,%d%n", &d1, &d2, &p) == 2 &&
  2497. d1 >= 0 && d1 < wh && d2 >= 0 && d2 < wh && d1 < d2 &&
  2498. (d2 - d1 == 1 || d2 - d1 == w)) {
  2499. /*
  2500. * Toggle domino presence between d1 and d2.
  2501. */
  2502. if (ret->grid[d1] == d2) {
  2503. assert(ret->grid[d2] == d1);
  2504. ret->grid[d1] = d1;
  2505. ret->grid[d2] = d2;
  2506. } else {
  2507. /*
  2508. * Erase any dominoes that might overlap the new one.
  2509. */
  2510. d3 = ret->grid[d1];
  2511. if (d3 != d1)
  2512. ret->grid[d3] = d3;
  2513. d3 = ret->grid[d2];
  2514. if (d3 != d2)
  2515. ret->grid[d3] = d3;
  2516. /*
  2517. * Place the new one.
  2518. */
  2519. ret->grid[d1] = d2;
  2520. ret->grid[d2] = d1;
  2521. /*
  2522. * Destroy any edges lurking around it.
  2523. */
  2524. if (ret->edges[d1] & EDGE_L) {
  2525. assert(d1 - 1 >= 0);
  2526. ret->edges[d1 - 1] &= ~EDGE_R;
  2527. }
  2528. if (ret->edges[d1] & EDGE_R) {
  2529. assert(d1 + 1 < wh);
  2530. ret->edges[d1 + 1] &= ~EDGE_L;
  2531. }
  2532. if (ret->edges[d1] & EDGE_T) {
  2533. assert(d1 - w >= 0);
  2534. ret->edges[d1 - w] &= ~EDGE_B;
  2535. }
  2536. if (ret->edges[d1] & EDGE_B) {
  2537. assert(d1 + 1 < wh);
  2538. ret->edges[d1 + w] &= ~EDGE_T;
  2539. }
  2540. ret->edges[d1] = 0;
  2541. if (ret->edges[d2] & EDGE_L) {
  2542. assert(d2 - 1 >= 0);
  2543. ret->edges[d2 - 1] &= ~EDGE_R;
  2544. }
  2545. if (ret->edges[d2] & EDGE_R) {
  2546. assert(d2 + 1 < wh);
  2547. ret->edges[d2 + 1] &= ~EDGE_L;
  2548. }
  2549. if (ret->edges[d2] & EDGE_T) {
  2550. assert(d2 - w >= 0);
  2551. ret->edges[d2 - w] &= ~EDGE_B;
  2552. }
  2553. if (ret->edges[d2] & EDGE_B) {
  2554. assert(d2 + 1 < wh);
  2555. ret->edges[d2 + w] &= ~EDGE_T;
  2556. }
  2557. ret->edges[d2] = 0;
  2558. }
  2559. move += p+1;
  2560. } else if (move[0] == 'E' &&
  2561. sscanf(move+1, "%d,%d%n", &d1, &d2, &p) == 2 &&
  2562. d1 >= 0 && d1 < wh && d2 >= 0 && d2 < wh && d1 < d2 &&
  2563. ret->grid[d1] == d1 && ret->grid[d2] == d2 &&
  2564. (d2 - d1 == 1 || d2 - d1 == w)) {
  2565. /*
  2566. * Toggle edge presence between d1 and d2.
  2567. */
  2568. if (d2 == d1 + 1) {
  2569. ret->edges[d1] ^= EDGE_R;
  2570. ret->edges[d2] ^= EDGE_L;
  2571. } else {
  2572. ret->edges[d1] ^= EDGE_B;
  2573. ret->edges[d2] ^= EDGE_T;
  2574. }
  2575. move += p+1;
  2576. } else {
  2577. free_game(ret);
  2578. return NULL;
  2579. }
  2580. if (*move) {
  2581. if (*move != ';') {
  2582. free_game(ret);
  2583. return NULL;
  2584. }
  2585. move++;
  2586. }
  2587. }
  2588. /*
  2589. * After modifying the grid, check completion.
  2590. */
  2591. if (!ret->completed) {
  2592. int i, ok = 0;
  2593. bool *used = snewn(TRI(n+1), bool);
  2594. memset(used, 0, TRI(n+1));
  2595. for (i = 0; i < wh; i++)
  2596. if (ret->grid[i] > i) {
  2597. int n1, n2, di;
  2598. n1 = ret->numbers->numbers[i];
  2599. n2 = ret->numbers->numbers[ret->grid[i]];
  2600. di = DINDEX(n1, n2);
  2601. assert(di >= 0 && di < TRI(n+1));
  2602. if (!used[di]) {
  2603. used[di] = true;
  2604. ok++;
  2605. }
  2606. }
  2607. sfree(used);
  2608. if (ok == DCOUNT(n))
  2609. ret->completed = true;
  2610. }
  2611. return ret;
  2612. }
  2613. /* ----------------------------------------------------------------------
  2614. * Drawing routines.
  2615. */
  2616. static void game_compute_size(const game_params *params, int tilesize,
  2617. const game_ui *ui, int *x, int *y)
  2618. {
  2619. int n = params->n, w = n+2, h = n+1;
  2620. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  2621. struct { int tilesize; } ads, *ds = &ads;
  2622. ads.tilesize = tilesize;
  2623. *x = w * TILESIZE + 2*BORDER;
  2624. *y = h * TILESIZE + 2*BORDER;
  2625. }
  2626. static void game_set_size(drawing *dr, game_drawstate *ds,
  2627. const game_params *params, int tilesize)
  2628. {
  2629. ds->tilesize = tilesize;
  2630. }
  2631. static float *game_colours(frontend *fe, int *ncolours)
  2632. {
  2633. float *ret = snewn(3 * NCOLOURS, float);
  2634. frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
  2635. ret[COL_TEXT * 3 + 0] = 0.0F;
  2636. ret[COL_TEXT * 3 + 1] = 0.0F;
  2637. ret[COL_TEXT * 3 + 2] = 0.0F;
  2638. ret[COL_DOMINO * 3 + 0] = 0.0F;
  2639. ret[COL_DOMINO * 3 + 1] = 0.0F;
  2640. ret[COL_DOMINO * 3 + 2] = 0.0F;
  2641. ret[COL_DOMINOCLASH * 3 + 0] = 0.5F;
  2642. ret[COL_DOMINOCLASH * 3 + 1] = 0.0F;
  2643. ret[COL_DOMINOCLASH * 3 + 2] = 0.0F;
  2644. ret[COL_DOMINOTEXT * 3 + 0] = 1.0F;
  2645. ret[COL_DOMINOTEXT * 3 + 1] = 1.0F;
  2646. ret[COL_DOMINOTEXT * 3 + 2] = 1.0F;
  2647. ret[COL_EDGE * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 2 / 3;
  2648. ret[COL_EDGE * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] * 2 / 3;
  2649. ret[COL_EDGE * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] * 2 / 3;
  2650. ret[COL_HIGHLIGHT_1 * 3 + 0] = 0.85;
  2651. ret[COL_HIGHLIGHT_1 * 3 + 1] = 0.20;
  2652. ret[COL_HIGHLIGHT_1 * 3 + 2] = 0.20;
  2653. ret[COL_HIGHLIGHT_2 * 3 + 0] = 0.30;
  2654. ret[COL_HIGHLIGHT_2 * 3 + 1] = 0.85;
  2655. ret[COL_HIGHLIGHT_2 * 3 + 2] = 0.20;
  2656. *ncolours = NCOLOURS;
  2657. return ret;
  2658. }
  2659. static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
  2660. {
  2661. struct game_drawstate *ds = snew(struct game_drawstate);
  2662. int i;
  2663. ds->w = state->w;
  2664. ds->h = state->h;
  2665. ds->visible = snewn(ds->w * ds->h, unsigned long);
  2666. ds->tilesize = 0; /* not decided yet */
  2667. for (i = 0; i < ds->w * ds->h; i++)
  2668. ds->visible[i] = 0xFFFF;
  2669. return ds;
  2670. }
  2671. static void game_free_drawstate(drawing *dr, game_drawstate *ds)
  2672. {
  2673. sfree(ds->visible);
  2674. sfree(ds);
  2675. }
  2676. enum {
  2677. TYPE_L,
  2678. TYPE_R,
  2679. TYPE_T,
  2680. TYPE_B,
  2681. TYPE_BLANK,
  2682. TYPE_MASK = 0x0F
  2683. };
  2684. /* These flags must be disjoint with:
  2685. * the above enum (TYPE_*) [0x000 -- 0x00F]
  2686. * EDGE_* [0x100 -- 0xF00]
  2687. * and must fit into an unsigned long (32 bits).
  2688. */
  2689. #define DF_HIGHLIGHT_1 0x10
  2690. #define DF_HIGHLIGHT_2 0x20
  2691. #define DF_FLASH 0x40
  2692. #define DF_CLASH 0x80
  2693. #define DF_CURSOR 0x01000
  2694. #define DF_CURSOR_USEFUL 0x02000
  2695. #define DF_CURSOR_XBASE 0x10000
  2696. #define DF_CURSOR_XMASK 0x30000
  2697. #define DF_CURSOR_YBASE 0x40000
  2698. #define DF_CURSOR_YMASK 0xC0000
  2699. #define CEDGE_OFF (TILESIZE / 8)
  2700. #define IS_EMPTY(s,x,y) ((s)->grid[(y)*(s)->w+(x)] == ((y)*(s)->w+(x)))
  2701. static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
  2702. int x, int y, int type, int highlight_1, int highlight_2)
  2703. {
  2704. int w = state->w /*, h = state->h */;
  2705. int cx = COORD(x), cy = COORD(y);
  2706. int nc;
  2707. char str[80];
  2708. int flags;
  2709. clip(dr, cx, cy, TILESIZE, TILESIZE);
  2710. draw_rect(dr, cx, cy, TILESIZE, TILESIZE, COL_BACKGROUND);
  2711. flags = type &~ TYPE_MASK;
  2712. type &= TYPE_MASK;
  2713. if (type != TYPE_BLANK) {
  2714. int i, bg;
  2715. /*
  2716. * Draw one end of a domino. This is composed of:
  2717. *
  2718. * - two filled circles (rounded corners)
  2719. * - two rectangles
  2720. * - a slight shift in the number
  2721. */
  2722. if (flags & DF_CLASH)
  2723. bg = COL_DOMINOCLASH;
  2724. else
  2725. bg = COL_DOMINO;
  2726. nc = COL_DOMINOTEXT;
  2727. if (flags & DF_FLASH) {
  2728. int tmp = nc;
  2729. nc = bg;
  2730. bg = tmp;
  2731. }
  2732. if (type == TYPE_L || type == TYPE_T)
  2733. draw_circle(dr, cx+DOMINO_COFFSET, cy+DOMINO_COFFSET,
  2734. DOMINO_RADIUS, bg, bg);
  2735. if (type == TYPE_R || type == TYPE_T)
  2736. draw_circle(dr, cx+TILESIZE-1-DOMINO_COFFSET, cy+DOMINO_COFFSET,
  2737. DOMINO_RADIUS, bg, bg);
  2738. if (type == TYPE_L || type == TYPE_B)
  2739. draw_circle(dr, cx+DOMINO_COFFSET, cy+TILESIZE-1-DOMINO_COFFSET,
  2740. DOMINO_RADIUS, bg, bg);
  2741. if (type == TYPE_R || type == TYPE_B)
  2742. draw_circle(dr, cx+TILESIZE-1-DOMINO_COFFSET,
  2743. cy+TILESIZE-1-DOMINO_COFFSET,
  2744. DOMINO_RADIUS, bg, bg);
  2745. for (i = 0; i < 2; i++) {
  2746. int x1, y1, x2, y2;
  2747. x1 = cx + (i ? DOMINO_GUTTER : DOMINO_COFFSET);
  2748. y1 = cy + (i ? DOMINO_COFFSET : DOMINO_GUTTER);
  2749. x2 = cx + TILESIZE-1 - (i ? DOMINO_GUTTER : DOMINO_COFFSET);
  2750. y2 = cy + TILESIZE-1 - (i ? DOMINO_COFFSET : DOMINO_GUTTER);
  2751. if (type == TYPE_L)
  2752. x2 = cx + TILESIZE + TILESIZE/16;
  2753. else if (type == TYPE_R)
  2754. x1 = cx - TILESIZE/16;
  2755. else if (type == TYPE_T)
  2756. y2 = cy + TILESIZE + TILESIZE/16;
  2757. else if (type == TYPE_B)
  2758. y1 = cy - TILESIZE/16;
  2759. draw_rect(dr, x1, y1, x2-x1+1, y2-y1+1, bg);
  2760. }
  2761. } else {
  2762. if (flags & EDGE_T)
  2763. draw_rect(dr, cx+DOMINO_GUTTER, cy,
  2764. TILESIZE-2*DOMINO_GUTTER, 1, COL_EDGE);
  2765. if (flags & EDGE_B)
  2766. draw_rect(dr, cx+DOMINO_GUTTER, cy+TILESIZE-1,
  2767. TILESIZE-2*DOMINO_GUTTER, 1, COL_EDGE);
  2768. if (flags & EDGE_L)
  2769. draw_rect(dr, cx, cy+DOMINO_GUTTER,
  2770. 1, TILESIZE-2*DOMINO_GUTTER, COL_EDGE);
  2771. if (flags & EDGE_R)
  2772. draw_rect(dr, cx+TILESIZE-1, cy+DOMINO_GUTTER,
  2773. 1, TILESIZE-2*DOMINO_GUTTER, COL_EDGE);
  2774. nc = COL_TEXT;
  2775. }
  2776. if (flags & DF_CURSOR) {
  2777. int curx = ((flags & DF_CURSOR_XMASK) / DF_CURSOR_XBASE) & 3;
  2778. int cury = ((flags & DF_CURSOR_YMASK) / DF_CURSOR_YBASE) & 3;
  2779. int ox = cx + curx*TILESIZE/2;
  2780. int oy = cy + cury*TILESIZE/2;
  2781. draw_rect_corners(dr, ox, oy, CURSOR_RADIUS, nc);
  2782. if (flags & DF_CURSOR_USEFUL)
  2783. draw_rect_corners(dr, ox, oy, CURSOR_RADIUS+1, nc);
  2784. }
  2785. if (flags & DF_HIGHLIGHT_1) {
  2786. nc = COL_HIGHLIGHT_1;
  2787. } else if (flags & DF_HIGHLIGHT_2) {
  2788. nc = COL_HIGHLIGHT_2;
  2789. }
  2790. sprintf(str, "%d", state->numbers->numbers[y*w+x]);
  2791. draw_text(dr, cx+TILESIZE/2, cy+TILESIZE/2, FONT_VARIABLE, TILESIZE/2,
  2792. ALIGN_HCENTRE | ALIGN_VCENTRE, nc, str);
  2793. draw_update(dr, cx, cy, TILESIZE, TILESIZE);
  2794. unclip(dr);
  2795. }
  2796. static void game_redraw(drawing *dr, game_drawstate *ds,
  2797. const game_state *oldstate, const game_state *state,
  2798. int dir, const game_ui *ui,
  2799. float animtime, float flashtime)
  2800. {
  2801. int n = state->params.n, w = state->w, h = state->h, wh = w*h;
  2802. int x, y, i;
  2803. unsigned char *used;
  2804. /*
  2805. * See how many dominoes of each type there are, so we can
  2806. * highlight clashes in red.
  2807. */
  2808. used = snewn(TRI(n+1), unsigned char);
  2809. memset(used, 0, TRI(n+1));
  2810. for (i = 0; i < wh; i++)
  2811. if (state->grid[i] > i) {
  2812. int n1, n2, di;
  2813. n1 = state->numbers->numbers[i];
  2814. n2 = state->numbers->numbers[state->grid[i]];
  2815. di = DINDEX(n1, n2);
  2816. assert(di >= 0 && di < TRI(n+1));
  2817. if (used[di] < 2)
  2818. used[di]++;
  2819. }
  2820. for (y = 0; y < h; y++)
  2821. for (x = 0; x < w; x++) {
  2822. int n = y*w+x;
  2823. int n1, n2, di;
  2824. unsigned long c;
  2825. if (state->grid[n] == n-1)
  2826. c = TYPE_R;
  2827. else if (state->grid[n] == n+1)
  2828. c = TYPE_L;
  2829. else if (state->grid[n] == n-w)
  2830. c = TYPE_B;
  2831. else if (state->grid[n] == n+w)
  2832. c = TYPE_T;
  2833. else
  2834. c = TYPE_BLANK;
  2835. n1 = state->numbers->numbers[n];
  2836. if (c != TYPE_BLANK) {
  2837. n2 = state->numbers->numbers[state->grid[n]];
  2838. di = DINDEX(n1, n2);
  2839. if (used[di] > 1)
  2840. c |= DF_CLASH; /* highlight a clash */
  2841. } else {
  2842. c |= state->edges[n];
  2843. }
  2844. if (n1 == ui->highlight_1)
  2845. c |= DF_HIGHLIGHT_1;
  2846. if (n1 == ui->highlight_2)
  2847. c |= DF_HIGHLIGHT_2;
  2848. if (flashtime != 0)
  2849. c |= DF_FLASH; /* we're flashing */
  2850. if (ui->cur_visible) {
  2851. unsigned curx = (unsigned)(ui->cur_x - (2*x-1));
  2852. unsigned cury = (unsigned)(ui->cur_y - (2*y-1));
  2853. if (curx < 3 && cury < 3) {
  2854. c |= (DF_CURSOR |
  2855. (curx * DF_CURSOR_XBASE) |
  2856. (cury * DF_CURSOR_YBASE));
  2857. if ((ui->cur_x ^ ui->cur_y) & 1)
  2858. c |= DF_CURSOR_USEFUL;
  2859. }
  2860. }
  2861. if (ds->visible[n] != c) {
  2862. draw_tile(dr, ds, state, x, y, c,
  2863. ui->highlight_1, ui->highlight_2);
  2864. ds->visible[n] = c;
  2865. }
  2866. }
  2867. sfree(used);
  2868. }
  2869. static float game_anim_length(const game_state *oldstate,
  2870. const game_state *newstate, int dir, game_ui *ui)
  2871. {
  2872. return 0.0F;
  2873. }
  2874. static float game_flash_length(const game_state *oldstate,
  2875. const game_state *newstate, int dir, game_ui *ui)
  2876. {
  2877. if (!oldstate->completed && newstate->completed &&
  2878. !oldstate->cheated && !newstate->cheated)
  2879. {
  2880. ui->highlight_1 = ui->highlight_2 = -1;
  2881. return FLASH_TIME;
  2882. }
  2883. return 0.0F;
  2884. }
  2885. static void game_get_cursor_location(const game_ui *ui,
  2886. const game_drawstate *ds,
  2887. const game_state *state,
  2888. const game_params *params,
  2889. int *x, int *y, int *w, int *h)
  2890. {
  2891. if(ui->cur_visible)
  2892. {
  2893. *x = BORDER + ((2 * ui->cur_x + 1) * TILESIZE) / 4;
  2894. *y = BORDER + ((2 * ui->cur_y + 1) * TILESIZE) / 4;
  2895. *w = *h = TILESIZE / 2 + 2;
  2896. }
  2897. }
  2898. static int game_status(const game_state *state)
  2899. {
  2900. return state->completed ? +1 : 0;
  2901. }
  2902. static void game_print_size(const game_params *params, const game_ui *ui,
  2903. float *x, float *y)
  2904. {
  2905. int pw, ph;
  2906. /*
  2907. * I'll use 6mm squares by default.
  2908. */
  2909. game_compute_size(params, 600, ui, &pw, &ph);
  2910. *x = pw / 100.0F;
  2911. *y = ph / 100.0F;
  2912. }
  2913. static void game_print(drawing *dr, const game_state *state, const game_ui *ui,
  2914. int tilesize)
  2915. {
  2916. int w = state->w, h = state->h;
  2917. int c, x, y;
  2918. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  2919. game_drawstate ads, *ds = &ads;
  2920. game_set_size(dr, ds, NULL, tilesize);
  2921. c = print_mono_colour(dr, 1); assert(c == COL_BACKGROUND);
  2922. c = print_mono_colour(dr, 0); assert(c == COL_TEXT);
  2923. c = print_mono_colour(dr, 0); assert(c == COL_DOMINO);
  2924. c = print_mono_colour(dr, 0); assert(c == COL_DOMINOCLASH);
  2925. c = print_mono_colour(dr, 1); assert(c == COL_DOMINOTEXT);
  2926. c = print_mono_colour(dr, 0); assert(c == COL_EDGE);
  2927. for (y = 0; y < h; y++)
  2928. for (x = 0; x < w; x++) {
  2929. int n = y*w+x;
  2930. unsigned long c;
  2931. if (state->grid[n] == n-1)
  2932. c = TYPE_R;
  2933. else if (state->grid[n] == n+1)
  2934. c = TYPE_L;
  2935. else if (state->grid[n] == n-w)
  2936. c = TYPE_B;
  2937. else if (state->grid[n] == n+w)
  2938. c = TYPE_T;
  2939. else
  2940. c = TYPE_BLANK;
  2941. draw_tile(dr, ds, state, x, y, c, -1, -1);
  2942. }
  2943. }
  2944. #ifdef COMBINED
  2945. #define thegame dominosa
  2946. #endif
  2947. const struct game thegame = {
  2948. "Dominosa", "games.dominosa", "dominosa",
  2949. default_params,
  2950. game_fetch_preset, NULL,
  2951. decode_params,
  2952. encode_params,
  2953. free_params,
  2954. dup_params,
  2955. true, game_configure, custom_params,
  2956. validate_params,
  2957. new_game_desc,
  2958. validate_desc,
  2959. new_game,
  2960. dup_game,
  2961. free_game,
  2962. true, solve_game,
  2963. true, game_can_format_as_text_now, game_text_format,
  2964. NULL, NULL, /* get_prefs, set_prefs */
  2965. new_ui,
  2966. free_ui,
  2967. NULL, /* encode_ui */
  2968. NULL, /* decode_ui */
  2969. NULL, /* game_request_keys */
  2970. game_changed_state,
  2971. current_key_label,
  2972. interpret_move,
  2973. execute_move,
  2974. PREFERRED_TILESIZE, game_compute_size, game_set_size,
  2975. game_colours,
  2976. game_new_drawstate,
  2977. game_free_drawstate,
  2978. game_redraw,
  2979. game_anim_length,
  2980. game_flash_length,
  2981. game_get_cursor_location,
  2982. game_status,
  2983. true, false, game_print_size, game_print,
  2984. false, /* wants_statusbar */
  2985. false, NULL, /* timing_state */
  2986. 0, /* flags */
  2987. };
  2988. #ifdef STANDALONE_SOLVER
  2989. int main(int argc, char **argv)
  2990. {
  2991. game_params *p;
  2992. game_state *s, *s2;
  2993. char *id = NULL, *desc;
  2994. int maxdiff = DIFFCOUNT;
  2995. const char *err;
  2996. bool grade = false, diagnostics = false;
  2997. struct solver_scratch *sc;
  2998. int retd;
  2999. while (--argc > 0) {
  3000. char *p = *++argv;
  3001. if (!strcmp(p, "-v")) {
  3002. diagnostics = true;
  3003. } else if (!strcmp(p, "-g")) {
  3004. grade = true;
  3005. } else if (!strncmp(p, "-d", 2) && p[2] && !p[3]) {
  3006. int i;
  3007. bool bad = true;
  3008. for (i = 0; i < lenof(dominosa_diffchars); i++)
  3009. if (dominosa_diffchars[i] != DIFF_AMBIGUOUS &&
  3010. dominosa_diffchars[i] == p[2]) {
  3011. bad = false;
  3012. maxdiff = i;
  3013. break;
  3014. }
  3015. if (bad) {
  3016. fprintf(stderr, "%s: unrecognised difficulty `%c'\n",
  3017. argv[0], p[2]);
  3018. return 1;
  3019. }
  3020. } else if (*p == '-') {
  3021. fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
  3022. return 1;
  3023. } else {
  3024. id = p;
  3025. }
  3026. }
  3027. if (!id) {
  3028. fprintf(stderr, "usage: %s [-v | -g] <game_id>\n", argv[0]);
  3029. return 1;
  3030. }
  3031. desc = strchr(id, ':');
  3032. if (!desc) {
  3033. fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]);
  3034. return 1;
  3035. }
  3036. *desc++ = '\0';
  3037. p = default_params();
  3038. decode_params(p, id);
  3039. err = validate_desc(p, desc);
  3040. if (err) {
  3041. fprintf(stderr, "%s: %s\n", argv[0], err);
  3042. return 1;
  3043. }
  3044. s = new_game(NULL, p, desc);
  3045. solver_diagnostics = diagnostics;
  3046. sc = solver_make_scratch(p->n);
  3047. solver_setup_grid(sc, s->numbers->numbers);
  3048. retd = run_solver(sc, maxdiff);
  3049. if (retd == 0) {
  3050. printf("Puzzle is inconsistent\n");
  3051. } else if (grade) {
  3052. printf("Difficulty rating: %s\n",
  3053. dominosa_diffnames[sc->max_diff_used]);
  3054. } else {
  3055. char *move, *text;
  3056. move = solution_move_string(sc);
  3057. s2 = execute_move(s, move);
  3058. text = game_text_format(s2);
  3059. sfree(move);
  3060. fputs(text, stdout);
  3061. sfree(text);
  3062. free_game(s2);
  3063. if (retd > 1)
  3064. printf("Could not deduce a unique solution\n");
  3065. }
  3066. solver_free_scratch(sc);
  3067. free_game(s);
  3068. free_params(p);
  3069. return 0;
  3070. }
  3071. #endif
  3072. /* vim: set shiftwidth=4 :set textwidth=80: */