singles.c 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036
  1. /*
  2. * singles.c: implementation of Hitori ('let me alone') from Nikoli.
  3. *
  4. * Make single-get able to fetch a specific puzzle ID from menneske.no?
  5. *
  6. * www.menneske.no solving methods:
  7. *
  8. * Done:
  9. * SC: if you circle a cell, any cells in same row/col with same no --> black
  10. * -- solver_op_circle
  11. * SB: if you make a cell black, any cells around it --> white
  12. * -- solver_op_blacken
  13. * ST: 3 identical cells in row, centre is white and outer two black.
  14. * SP: 2 identical cells with single-cell gap, middle cell is white.
  15. * -- solver_singlesep (both ST and SP)
  16. * PI: if you have a pair of same number in row/col, any other
  17. * cells of same number must be black.
  18. * -- solve_doubles
  19. * CC: if you have a black on edge one cell away from corner, cell
  20. * on edge diag. adjacent must be white.
  21. * CE: if you have 2 black cells of triangle on edge, third cell must
  22. * be white.
  23. * QM: if you have 3 black cells of diagonal square in middle, fourth
  24. * cell must be white.
  25. * -- solve_allblackbutone (CC, CE, and QM).
  26. * QC: a corner with 4 identical numbers (or 2 and 2) must have the
  27. * corner cell (and cell diagonal to that) black.
  28. * TC: a corner with 3 identical numbers (with the L either way)
  29. * must have the apex of L black, and other two white.
  30. * DC: a corner with 2 identical numbers in domino can set a white
  31. * cell along wall.
  32. * -- solve_corners (QC, TC, DC)
  33. * IP: pair with one-offset-pair force whites by offset pair
  34. * -- solve_offsetpair
  35. * MC: any cells diag. adjacent to black cells that would split board
  36. * into separate white regions must be white.
  37. * -- solve_removesplits
  38. *
  39. * Still to do:
  40. *
  41. * TEP: 3 pairs of dominos parallel to side, can mark 4 white cells
  42. * alongside.
  43. * DEP: 2 pairs of dominos parallel to side, can mark 2 white cells.
  44. * FI: if you have two sets of double-cells packed together, singles
  45. * in that row/col must be white (qv. PI)
  46. * QuM: four identical cells (or 2 and 2) in middle of grid only have
  47. * two possible solutions each.
  48. * FDE: doubles one row/column away from edge can force a white cell.
  49. * FDM: doubles in centre (next to bits of diag. square) can force a white cell.
  50. * MP: two pairs with same number between force number to black.
  51. * CnC: if circling a cell leads to impossible board, cell is black.
  52. * MC: if we have two possiblilities, can we force a white circle?
  53. *
  54. */
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <assert.h>
  59. #include <ctype.h>
  60. #ifdef NO_TGMATH_H
  61. # include <math.h>
  62. #else
  63. # include <tgmath.h>
  64. #endif
  65. #include "puzzles.h"
  66. #include "latin.h"
  67. #ifdef STANDALONE_SOLVER
  68. static bool verbose = false;
  69. #endif
  70. #define PREFERRED_TILE_SIZE 32
  71. #define TILE_SIZE (ds->tilesize)
  72. #define BORDER (TILE_SIZE / 2)
  73. #define CRAD ((TILE_SIZE / 2) - 1)
  74. #define TEXTSZ ((14*CRAD/10) - 1) /* 2 * sqrt(2) of CRAD */
  75. #define COORD(x) ( (x) * TILE_SIZE + BORDER )
  76. #define FROMCOORD(x) ( ((x) - BORDER + TILE_SIZE) / TILE_SIZE - 1 )
  77. #define INGRID(s,x,y) ((x) >= 0 && (x) < (s)->w && (y) >= 0 && (y) < (s)->h)
  78. #define FLASH_TIME 0.7F
  79. enum {
  80. COL_BACKGROUND, COL_UNUSED1, COL_LOWLIGHT,
  81. COL_BLACK, COL_WHITE, COL_BLACKNUM, COL_GRID,
  82. COL_CURSOR, COL_ERROR,
  83. NCOLOURS
  84. };
  85. struct game_params {
  86. int w, h, diff;
  87. };
  88. #define F_BLACK 0x1
  89. #define F_CIRCLE 0x2
  90. #define F_ERROR 0x4
  91. #define F_SCRATCH 0x8
  92. struct game_state {
  93. int w, h, n, o; /* n = w*h; o = max(w, h) */
  94. bool completed, used_solve, impossible;
  95. int *nums; /* size w*h */
  96. unsigned int *flags; /* size w*h */
  97. };
  98. /* top, right, bottom, left */
  99. static const int dxs[4] = { 0, 1, 0, -1 };
  100. static const int dys[4] = { -1, 0, 1, 0 };
  101. /* --- Game parameters and preset functions --- */
  102. #define DIFFLIST(A) \
  103. A(EASY,Easy,e) \
  104. A(TRICKY,Tricky,k)
  105. #define ENUM(upper,title,lower) DIFF_ ## upper,
  106. #define TITLE(upper,title,lower) #title,
  107. #define ENCODE(upper,title,lower) #lower
  108. #define CONFIG(upper,title,lower) ":" #title
  109. enum { DIFFLIST(ENUM) DIFF_MAX, DIFF_ANY };
  110. static char const *const singles_diffnames[] = { DIFFLIST(TITLE) };
  111. static char const singles_diffchars[] = DIFFLIST(ENCODE);
  112. #define DIFFCOUNT lenof(singles_diffchars)
  113. #define DIFFCONFIG DIFFLIST(CONFIG)
  114. static game_params *default_params(void)
  115. {
  116. game_params *ret = snew(game_params);
  117. ret->w = ret->h = 5;
  118. ret->diff = DIFF_EASY;
  119. return ret;
  120. }
  121. static const struct game_params singles_presets[] = {
  122. { 5, 5, DIFF_EASY },
  123. { 5, 5, DIFF_TRICKY },
  124. { 6, 6, DIFF_EASY },
  125. { 6, 6, DIFF_TRICKY },
  126. { 8, 8, DIFF_EASY },
  127. { 8, 8, DIFF_TRICKY },
  128. { 10, 10, DIFF_EASY },
  129. { 10, 10, DIFF_TRICKY },
  130. { 12, 12, DIFF_EASY },
  131. { 12, 12, DIFF_TRICKY }
  132. };
  133. static bool game_fetch_preset(int i, char **name, game_params **params)
  134. {
  135. game_params *ret;
  136. char buf[80];
  137. if (i < 0 || i >= lenof(singles_presets))
  138. return false;
  139. ret = default_params();
  140. *ret = singles_presets[i];
  141. *params = ret;
  142. sprintf(buf, "%dx%d %s", ret->w, ret->h, singles_diffnames[ret->diff]);
  143. *name = dupstr(buf);
  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 *ret, char const *string)
  157. {
  158. char const *p = string;
  159. int i;
  160. ret->w = ret->h = atoi(p);
  161. while (*p && isdigit((unsigned char)*p)) p++;
  162. if (*p == 'x') {
  163. p++;
  164. ret->h = atoi(p);
  165. while (*p && isdigit((unsigned char)*p)) p++;
  166. }
  167. if (*p == 'd') {
  168. ret->diff = DIFF_MAX; /* which is invalid */
  169. p++;
  170. for (i = 0; i < DIFFCOUNT; i++) {
  171. if (*p == singles_diffchars[i])
  172. ret->diff = i;
  173. }
  174. p++;
  175. }
  176. }
  177. static char *encode_params(const game_params *params, bool full)
  178. {
  179. char data[256];
  180. if (full)
  181. sprintf(data, "%dx%dd%c", params->w, params->h, singles_diffchars[params->diff]);
  182. else
  183. sprintf(data, "%dx%d", params->w, params->h);
  184. return dupstr(data);
  185. }
  186. static config_item *game_configure(const game_params *params)
  187. {
  188. config_item *ret;
  189. char buf[80];
  190. ret = snewn(4, config_item);
  191. ret[0].name = "Width";
  192. ret[0].type = C_STRING;
  193. sprintf(buf, "%d", params->w);
  194. ret[0].u.string.sval = dupstr(buf);
  195. ret[1].name = "Height";
  196. ret[1].type = C_STRING;
  197. sprintf(buf, "%d", params->h);
  198. ret[1].u.string.sval = dupstr(buf);
  199. ret[2].name = "Difficulty";
  200. ret[2].type = C_CHOICES;
  201. ret[2].u.choices.choicenames = DIFFCONFIG;
  202. ret[2].u.choices.selected = params->diff;
  203. ret[3].name = NULL;
  204. ret[3].type = C_END;
  205. return ret;
  206. }
  207. static game_params *custom_params(const config_item *cfg)
  208. {
  209. game_params *ret = snew(game_params);
  210. ret->w = atoi(cfg[0].u.string.sval);
  211. ret->h = atoi(cfg[1].u.string.sval);
  212. ret->diff = cfg[2].u.choices.selected;
  213. return ret;
  214. }
  215. static const char *validate_params(const game_params *params, bool full)
  216. {
  217. if (params->w < 2 || params->h < 2)
  218. return "Width and neight must be at least two";
  219. if (params->w > 10+26+26 || params->h > 10+26+26)
  220. return "Puzzle is too large";
  221. if (full) {
  222. if (params->diff < 0 || params->diff >= DIFF_MAX)
  223. return "Unknown difficulty rating";
  224. }
  225. return NULL;
  226. }
  227. /* --- Game description string generation and unpicking --- */
  228. static game_state *blank_game(int w, int h)
  229. {
  230. game_state *state = snew(game_state);
  231. memset(state, 0, sizeof(game_state));
  232. state->w = w;
  233. state->h = h;
  234. state->n = w*h;
  235. state->o = max(w,h);
  236. state->completed = false;
  237. state->used_solve = false;
  238. state->impossible = false;
  239. state->nums = snewn(state->n, int);
  240. state->flags = snewn(state->n, unsigned int);
  241. memset(state->nums, 0, state->n*sizeof(int));
  242. memset(state->flags, 0, state->n*sizeof(unsigned int));
  243. return state;
  244. }
  245. static game_state *dup_game(const game_state *state)
  246. {
  247. game_state *ret = blank_game(state->w, state->h);
  248. ret->completed = state->completed;
  249. ret->used_solve = state->used_solve;
  250. ret->impossible = state->impossible;
  251. memcpy(ret->nums, state->nums, state->n*sizeof(int));
  252. memcpy(ret->flags, state->flags, state->n*sizeof(unsigned int));
  253. return ret;
  254. }
  255. static void free_game(game_state *state)
  256. {
  257. sfree(state->nums);
  258. sfree(state->flags);
  259. sfree(state);
  260. }
  261. static char n2c(int num) {
  262. if (num < 10)
  263. return '0' + num;
  264. else if (num < 10+26)
  265. return 'a' + num - 10;
  266. else
  267. return 'A' + num - 10 - 26;
  268. return '?';
  269. }
  270. static int c2n(char c) {
  271. if (isdigit((unsigned char)c))
  272. return (int)(c - '0');
  273. else if (c >= 'a' && c <= 'z')
  274. return (int)(c - 'a' + 10);
  275. else if (c >= 'A' && c <= 'Z')
  276. return (int)(c - 'A' + 10 + 26);
  277. return -1;
  278. }
  279. static void unpick_desc(const game_params *params, const char *desc,
  280. game_state **sout, const char **mout)
  281. {
  282. game_state *state = blank_game(params->w, params->h);
  283. const char *msg = NULL;
  284. int num = 0, i = 0;
  285. if (strlen(desc) != state->n) {
  286. msg = "Game description is wrong length";
  287. goto done;
  288. }
  289. for (i = 0; i < state->n; i++) {
  290. num = c2n(desc[i]);
  291. if (num <= 0 || num > state->o) {
  292. msg = "Game description contains unexpected characters";
  293. goto done;
  294. }
  295. state->nums[i] = num;
  296. }
  297. done:
  298. if (msg) { /* sth went wrong. */
  299. if (mout) *mout = msg;
  300. free_game(state);
  301. } else {
  302. if (mout) *mout = NULL;
  303. if (sout) *sout = state;
  304. else free_game(state);
  305. }
  306. }
  307. static char *generate_desc(game_state *state, bool issolve)
  308. {
  309. char *ret = snewn(state->n+1+(issolve?1:0), char);
  310. int i, p=0;
  311. if (issolve)
  312. ret[p++] = 'S';
  313. for (i = 0; i < state->n; i++)
  314. ret[p++] = n2c(state->nums[i]);
  315. ret[p] = '\0';
  316. return ret;
  317. }
  318. /* --- Useful game functions (completion, etc.) --- */
  319. static bool game_can_format_as_text_now(const game_params *params)
  320. {
  321. return true;
  322. }
  323. static char *game_text_format(const game_state *state)
  324. {
  325. int len, x, y, i;
  326. char *ret, *p;
  327. len = (state->w)*2; /* one row ... */
  328. len = len * (state->h*2); /* ... h rows, including gaps ... */
  329. len += 1; /* ... final NL */
  330. p = ret = snewn(len, char);
  331. for (y = 0; y < state->h; y++) {
  332. for (x = 0; x < state->w; x++) {
  333. i = y*state->w + x;
  334. if (x > 0) *p++ = ' ';
  335. *p++ = (state->flags[i] & F_BLACK) ? '*' : n2c(state->nums[i]);
  336. }
  337. *p++ = '\n';
  338. for (x = 0; x < state->w; x++) {
  339. i = y*state->w + x;
  340. if (x > 0) *p++ = ' ';
  341. *p++ = (state->flags[i] & F_CIRCLE) ? '~' : ' ';
  342. }
  343. *p++ = '\n';
  344. }
  345. *p++ = '\0';
  346. assert(p - ret == len);
  347. return ret;
  348. }
  349. static void debug_state(const char *desc, game_state *state) {
  350. char *dbg = game_text_format(state);
  351. debug(("%s:\n%s", desc, dbg));
  352. sfree(dbg);
  353. }
  354. static void connect_if_same(game_state *state, DSF *dsf, int i1, int i2)
  355. {
  356. int c1, c2;
  357. if ((state->flags[i1] & F_BLACK) != (state->flags[i2] & F_BLACK))
  358. return;
  359. c1 = dsf_canonify(dsf, i1);
  360. c2 = dsf_canonify(dsf, i2);
  361. dsf_merge(dsf, c1, c2);
  362. }
  363. static void connect_dsf(game_state *state, DSF *dsf)
  364. {
  365. int x, y, i;
  366. /* Construct a dsf array for connected blocks; connections
  367. * tracked to right and down. */
  368. dsf_reinit(dsf);
  369. for (x = 0; x < state->w; x++) {
  370. for (y = 0; y < state->h; y++) {
  371. i = y*state->w + x;
  372. if (x < state->w-1)
  373. connect_if_same(state, dsf, i, i+1); /* right */
  374. if (y < state->h-1)
  375. connect_if_same(state, dsf, i, i+state->w); /* down */
  376. }
  377. }
  378. }
  379. #define CC_MARK_ERRORS 1
  380. #define CC_MUST_FILL 2
  381. static int check_rowcol(game_state *state, int starti, int di, int sz, unsigned flags)
  382. {
  383. int nerr = 0, n, m, i, j;
  384. /* if any circled numbers have identical non-circled numbers on
  385. * same row/column, error (non-circled)
  386. * if any circled numbers in same column are same number, highlight them.
  387. * if any rows/columns have >1 of same number, not complete. */
  388. for (n = 0, i = starti; n < sz; n++, i += di) {
  389. if (state->flags[i] & F_BLACK) continue;
  390. for (m = n+1, j = i+di; m < sz; m++, j += di) {
  391. if (state->flags[j] & F_BLACK) continue;
  392. if (state->nums[i] != state->nums[j]) continue;
  393. nerr++; /* ok, we have two numbers the same in a row. */
  394. if (!(flags & CC_MARK_ERRORS)) continue;
  395. /* If we have two circles in the same row around
  396. * two identical numbers, they are _both_ wrong. */
  397. if ((state->flags[i] & F_CIRCLE) &&
  398. (state->flags[j] & F_CIRCLE)) {
  399. state->flags[i] |= F_ERROR;
  400. state->flags[j] |= F_ERROR;
  401. }
  402. /* Otherwise, if we have a circle, any other identical
  403. * numbers in that row are obviously wrong. We don't
  404. * highlight this, however, since it makes the process
  405. * of solving the puzzle too easy (you circle a number
  406. * and it promptly tells you which numbers to blacken! */
  407. #if 0
  408. else if (state->flags[i] & F_CIRCLE)
  409. state->flags[j] |= F_ERROR;
  410. else if (state->flags[j] & F_CIRCLE)
  411. state->flags[i] |= F_ERROR;
  412. #endif
  413. }
  414. }
  415. return nerr;
  416. }
  417. static bool check_complete(game_state *state, unsigned flags)
  418. {
  419. DSF *dsf = dsf_new(state->n);
  420. int x, y, i, error = 0, nwhite, w = state->w, h = state->h;
  421. if (flags & CC_MARK_ERRORS) {
  422. for (i = 0; i < state->n; i++)
  423. state->flags[i] &= ~F_ERROR;
  424. }
  425. connect_dsf(state, dsf);
  426. /* If we're the solver we need the grid all to be definitively
  427. * black or definitively white (i.e. circled) otherwise the solver
  428. * has found an ambiguous grid. */
  429. if (flags & CC_MUST_FILL) {
  430. for (i = 0; i < state->n; i++) {
  431. if (!(state->flags[i] & F_BLACK) && !(state->flags[i] & F_CIRCLE))
  432. error += 1;
  433. }
  434. }
  435. /* Mark any black squares in groups of >1 as errors.
  436. * Count number of white squares. */
  437. nwhite = 0;
  438. for (i = 0; i < state->n; i++) {
  439. if (state->flags[i] & F_BLACK) {
  440. if (dsf_size(dsf, i) > 1) {
  441. error += 1;
  442. if (flags & CC_MARK_ERRORS)
  443. state->flags[i] |= F_ERROR;
  444. }
  445. } else
  446. nwhite += 1;
  447. }
  448. /* Check attributes of white squares, row- and column-wise. */
  449. for (x = 0; x < w; x++) /* check cols from (x,0) */
  450. error += check_rowcol(state, x, w, h, flags);
  451. for (y = 0; y < h; y++) /* check rows from (0,y) */
  452. error += check_rowcol(state, y*w, 1, w, flags);
  453. /* If there's more than one white region, pick the largest one to
  454. * be the canonical one (arbitrarily tie-breaking towards lower
  455. * array indices), and mark all the others as erroneous. */
  456. {
  457. int largest = 0, canonical = -1;
  458. for (i = 0; i < state->n; i++)
  459. if (!(state->flags[i] & F_BLACK)) {
  460. int size = dsf_size(dsf, i);
  461. if (largest < size) {
  462. largest = size;
  463. canonical = i;
  464. }
  465. }
  466. if (largest < nwhite) {
  467. for (i = 0; i < state->n; i++)
  468. if (!(state->flags[i] & F_BLACK) &&
  469. dsf_canonify(dsf, i) != canonical) {
  470. error += 1;
  471. if (flags & CC_MARK_ERRORS)
  472. state->flags[i] |= F_ERROR;
  473. }
  474. }
  475. }
  476. dsf_free(dsf);
  477. return !(error > 0);
  478. }
  479. static char *game_state_diff(const game_state *src, const game_state *dst,
  480. bool issolve)
  481. {
  482. char *ret = NULL, buf[80], c;
  483. int retlen = 0, x, y, i, k;
  484. unsigned int fmask = F_BLACK | F_CIRCLE;
  485. assert(src->n == dst->n);
  486. if (issolve) {
  487. ret = sresize(ret, 3, char);
  488. ret[0] = 'S'; ret[1] = ';'; ret[2] = '\0';
  489. retlen += 2;
  490. }
  491. for (x = 0; x < dst->w; x++) {
  492. for (y = 0; y < dst->h; y++) {
  493. i = y*dst->w + x;
  494. if ((src->flags[i] & fmask) != (dst->flags[i] & fmask)) {
  495. assert((dst->flags[i] & fmask) != fmask);
  496. if (dst->flags[i] & F_BLACK)
  497. c = 'B';
  498. else if (dst->flags[i] & F_CIRCLE)
  499. c = 'C';
  500. else
  501. c = 'E';
  502. k = sprintf(buf, "%c%d,%d;", (int)c, x, y);
  503. ret = sresize(ret, retlen + k + 1, char);
  504. strcpy(ret + retlen, buf);
  505. retlen += k;
  506. }
  507. }
  508. }
  509. return ret;
  510. }
  511. /* --- Solver --- */
  512. enum { BLACK, CIRCLE };
  513. struct solver_op {
  514. int x, y, op; /* op one of BLACK or CIRCLE. */
  515. const char *desc; /* must be non-malloced. */
  516. };
  517. struct solver_state {
  518. struct solver_op *ops;
  519. int n_ops, n_alloc;
  520. int *scratch;
  521. };
  522. static struct solver_state *solver_state_new(game_state *state)
  523. {
  524. struct solver_state *ss = snew(struct solver_state);
  525. ss->ops = NULL;
  526. ss->n_ops = ss->n_alloc = 0;
  527. ss->scratch = snewn(state->n, int);
  528. return ss;
  529. }
  530. static void solver_state_free(struct solver_state *ss)
  531. {
  532. sfree(ss->scratch);
  533. if (ss->ops) sfree(ss->ops);
  534. sfree(ss);
  535. }
  536. static void solver_op_add(struct solver_state *ss, int x, int y, int op, const char *desc)
  537. {
  538. struct solver_op *sop;
  539. if (ss->n_alloc < ss->n_ops + 1) {
  540. ss->n_alloc = (ss->n_alloc + 1) * 2;
  541. ss->ops = sresize(ss->ops, ss->n_alloc, struct solver_op);
  542. }
  543. sop = &(ss->ops[ss->n_ops++]);
  544. sop->x = x; sop->y = y; sop->op = op; sop->desc = desc;
  545. debug(("added solver op %s ('%s') at (%d,%d)\n",
  546. op == BLACK ? "BLACK" : "CIRCLE", desc, x, y));
  547. }
  548. static void solver_op_circle(game_state *state, struct solver_state *ss,
  549. int x, int y)
  550. {
  551. int i = y*state->w + x;
  552. if (!INGRID(state, x, y)) return;
  553. if (state->flags[i] & F_BLACK) {
  554. debug(("... solver wants to add auto-circle on black (%d,%d)\n", x, y));
  555. state->impossible = true;
  556. return;
  557. }
  558. /* Only add circle op if it's not already circled. */
  559. if (!(state->flags[i] & F_CIRCLE)) {
  560. solver_op_add(ss, x, y, CIRCLE, "SB - adjacent to black square");
  561. }
  562. }
  563. static void solver_op_blacken(game_state *state, struct solver_state *ss,
  564. int x, int y, int num)
  565. {
  566. int i = y*state->w + x;
  567. if (!INGRID(state, x, y)) return;
  568. if (state->nums[i] != num) return;
  569. if (state->flags[i] & F_CIRCLE) {
  570. debug(("... solver wants to add auto-black on circled(%d,%d)\n", x, y));
  571. state->impossible = true;
  572. return;
  573. }
  574. /* Only add black op if it's not already black. */
  575. if (!(state->flags[i] & F_BLACK)) {
  576. solver_op_add(ss, x, y, BLACK, "SC - number on same row/col as circled");
  577. }
  578. }
  579. static int solver_ops_do(game_state *state, struct solver_state *ss)
  580. {
  581. int next_op = 0, i, x, y, n_ops = 0;
  582. struct solver_op op;
  583. /* Care here: solver_op_* may call solver_op_add which may extend the
  584. * ss->n_ops. */
  585. while (next_op < ss->n_ops) {
  586. op = ss->ops[next_op++]; /* copy this away, it may get reallocated. */
  587. i = op.y*state->w + op.x;
  588. if (op.op == BLACK) {
  589. if (state->flags[i] & F_CIRCLE) {
  590. debug(("Solver wants to blacken circled square (%d,%d)!\n", op.x, op.y));
  591. state->impossible = true;
  592. return n_ops;
  593. }
  594. if (!(state->flags[i] & F_BLACK)) {
  595. debug(("... solver adding black at (%d,%d): %s\n", op.x, op.y, op.desc));
  596. #ifdef STANDALONE_SOLVER
  597. if (verbose)
  598. printf("Adding black at (%d,%d): %s\n", op.x, op.y, op.desc);
  599. #endif
  600. state->flags[i] |= F_BLACK;
  601. /*debug_state("State after adding black", state);*/
  602. n_ops++;
  603. solver_op_circle(state, ss, op.x-1, op.y);
  604. solver_op_circle(state, ss, op.x+1, op.y);
  605. solver_op_circle(state, ss, op.x, op.y-1);
  606. solver_op_circle(state, ss, op.x, op.y+1);
  607. }
  608. } else {
  609. if (state->flags[i] & F_BLACK) {
  610. debug(("Solver wants to circle blackened square (%d,%d)!\n", op.x, op.y));
  611. state->impossible = true;
  612. return n_ops;
  613. }
  614. if (!(state->flags[i] & F_CIRCLE)) {
  615. debug(("... solver adding circle at (%d,%d): %s\n", op.x, op.y, op.desc));
  616. #ifdef STANDALONE_SOLVER
  617. if (verbose)
  618. printf("Adding circle at (%d,%d): %s\n", op.x, op.y, op.desc);
  619. #endif
  620. state->flags[i] |= F_CIRCLE;
  621. /*debug_state("State after adding circle", state);*/
  622. n_ops++;
  623. for (x = 0; x < state->w; x++) {
  624. if (x != op.x)
  625. solver_op_blacken(state, ss, x, op.y, state->nums[i]);
  626. }
  627. for (y = 0; y < state->h; y++) {
  628. if (y != op.y)
  629. solver_op_blacken(state, ss, op.x, y, state->nums[i]);
  630. }
  631. }
  632. }
  633. }
  634. ss->n_ops = 0;
  635. return n_ops;
  636. }
  637. /* If the grid has two identical numbers with one cell between them, the inner
  638. * cell _must_ be white (and thus circled); (at least) one of the two must be
  639. * black (since they're in the same column or row) and thus the middle cell is
  640. * next to a black cell. */
  641. static int solve_singlesep(game_state *state, struct solver_state *ss)
  642. {
  643. int x, y, i, ir, irr, id, idd, n_ops = ss->n_ops;
  644. for (x = 0; x < state->w; x++) {
  645. for (y = 0; y < state->h; y++) {
  646. i = y*state->w + x;
  647. /* Cell two to our right? */
  648. ir = i + 1; irr = ir + 1;
  649. if (x < (state->w-2) &&
  650. state->nums[i] == state->nums[irr] &&
  651. !(state->flags[ir] & F_CIRCLE)) {
  652. solver_op_add(ss, x+1, y, CIRCLE, "SP/ST - between identical nums");
  653. }
  654. /* Cell two below us? */
  655. id = i + state->w; idd = id + state->w;
  656. if (y < (state->h-2) &&
  657. state->nums[i] == state->nums[idd] &&
  658. !(state->flags[id] & F_CIRCLE)) {
  659. solver_op_add(ss, x, y+1, CIRCLE, "SP/ST - between identical nums");
  660. }
  661. }
  662. }
  663. return ss->n_ops - n_ops;
  664. }
  665. /* If we have two identical numbers next to each other (in a row or column),
  666. * any other identical numbers in that column must be black. */
  667. static int solve_doubles(game_state *state, struct solver_state *ss)
  668. {
  669. int x, y, i, ii, n_ops = ss->n_ops, xy;
  670. for (y = 0, i = 0; y < state->h; y++) {
  671. for (x = 0; x < state->w; x++, i++) {
  672. assert(i == y*state->w+x);
  673. if (state->flags[i] & F_BLACK) continue;
  674. ii = i+1; /* check cell to our right. */
  675. if (x < (state->w-1) &&
  676. !(state->flags[ii] & F_BLACK) &&
  677. state->nums[i] == state->nums[ii]) {
  678. for (xy = 0; xy < state->w; xy++) {
  679. if (xy == x || xy == (x+1)) continue;
  680. if (state->nums[y*state->w + xy] == state->nums[i] &&
  681. !(state->flags[y*state->w + xy] & F_BLACK))
  682. solver_op_add(ss, xy, y, BLACK, "PI - same row as pair");
  683. }
  684. }
  685. ii = i+state->w; /* check cell below us */
  686. if (y < (state->h-1) &&
  687. !(state->flags[ii] & F_BLACK) &&
  688. state->nums[i] == state->nums[ii]) {
  689. for (xy = 0; xy < state->h; xy++) {
  690. if (xy == y || xy == (y+1)) continue;
  691. if (state->nums[xy*state->w + x] == state->nums[i] &&
  692. !(state->flags[xy*state->w + x] & F_BLACK))
  693. solver_op_add(ss, x, xy, BLACK, "PI - same col as pair");
  694. }
  695. }
  696. }
  697. }
  698. return ss->n_ops - n_ops;
  699. }
  700. /* If a white square has all-but-one possible adjacent squares black, the
  701. * one square left over must be white. */
  702. static int solve_allblackbutone(game_state *state, struct solver_state *ss)
  703. {
  704. int x, y, i, n_ops = ss->n_ops, xd, yd, id, ifree;
  705. int dis[4], d;
  706. dis[0] = -state->w;
  707. dis[1] = 1;
  708. dis[2] = state->w;
  709. dis[3] = -1;
  710. for (y = 0, i = 0; y < state->h; y++) {
  711. for (x = 0; x < state->w; x++, i++) {
  712. assert(i == y*state->w+x);
  713. if (state->flags[i] & F_BLACK) continue;
  714. ifree = -1;
  715. for (d = 0; d < 4; d++) {
  716. xd = x + dxs[d]; yd = y + dys[d]; id = i + dis[d];
  717. if (!INGRID(state, xd, yd)) continue;
  718. if (state->flags[id] & F_CIRCLE)
  719. goto skip; /* this cell already has a way out */
  720. if (!(state->flags[id] & F_BLACK)) {
  721. if (ifree != -1)
  722. goto skip; /* this cell has >1 white cell around it. */
  723. ifree = id;
  724. }
  725. }
  726. if (ifree != -1)
  727. solver_op_add(ss, ifree%state->w, ifree/state->w, CIRCLE,
  728. "CC/CE/QM: white cell with single non-black around it");
  729. else {
  730. debug(("White cell with no escape at (%d,%d)\n", x, y));
  731. state->impossible = true;
  732. return 0;
  733. }
  734. skip: ;
  735. }
  736. }
  737. return ss->n_ops - n_ops;
  738. }
  739. /* If we have 4 numbers the same in a 2x2 corner, the far corner and the
  740. * diagonally-adjacent square must both be black.
  741. * If we have 3 numbers the same in a 2x2 corner, the apex of the L
  742. * thus formed must be black.
  743. * If we have 2 numbers the same in a 2x2 corner, the non-same cell
  744. * one away from the corner must be white. */
  745. static void solve_corner(game_state *state, struct solver_state *ss,
  746. int x, int y, int dx, int dy)
  747. {
  748. int is[4], ns[4], xx, yy, w = state->w;
  749. for (yy = 0; yy < 2; yy++) {
  750. for (xx = 0; xx < 2; xx++) {
  751. is[yy*2+xx] = (y + dy*yy) * w + (x + dx*xx);
  752. ns[yy*2+xx] = state->nums[is[yy*2+xx]];
  753. }
  754. } /* order is now (corner, side 1, side 2, inner) */
  755. if (ns[0] == ns[1] && ns[0] == ns[2] && ns[0] == ns[3]) {
  756. solver_op_add(ss, is[0]%w, is[0]/w, BLACK, "QC: corner with 4 matching");
  757. solver_op_add(ss, is[3]%w, is[3]/w, BLACK, "QC: corner with 4 matching");
  758. } else if (ns[0] == ns[1] && ns[0] == ns[2]) {
  759. /* corner and 2 sides: apex is corner. */
  760. solver_op_add(ss, is[0]%w, is[0]/w, BLACK, "TC: corner apex from 3 matching");
  761. } else if (ns[1] == ns[2] && ns[1] == ns[3]) {
  762. /* side, side, fourth: apex is fourth. */
  763. solver_op_add(ss, is[3]%w, is[3]/w, BLACK, "TC: inside apex from 3 matching");
  764. } else if (ns[0] == ns[1] || ns[1] == ns[3]) {
  765. /* either way here we match the non-identical side. */
  766. solver_op_add(ss, is[2]%w, is[2]/w, CIRCLE, "DC: corner with 2 matching");
  767. } else if (ns[0] == ns[2] || ns[2] == ns[3]) {
  768. /* ditto */
  769. solver_op_add(ss, is[1]%w, is[1]/w, CIRCLE, "DC: corner with 2 matching");
  770. }
  771. }
  772. static int solve_corners(game_state *state, struct solver_state *ss)
  773. {
  774. int n_ops = ss->n_ops;
  775. solve_corner(state, ss, 0, 0, 1, 1);
  776. solve_corner(state, ss, state->w-1, 0, -1, 1);
  777. solve_corner(state, ss, state->w-1, state->h-1, -1, -1);
  778. solve_corner(state, ss, 0, state->h-1, 1, -1);
  779. return ss->n_ops - n_ops;
  780. }
  781. /* If you have the following situation:
  782. * ...
  783. * ...x A x x y A x...
  784. * ...x B x x B y x...
  785. * ...
  786. * then both squares marked 'y' must be white. One of the left-most A or B must
  787. * be white (since two side-by-side black cells are disallowed), which means
  788. * that the corresponding right-most A or B must be black (since you can't
  789. * have two of the same number on one line); thus, the adjacent squares
  790. * to that right-most A or B must be white, which include the two marked 'y'
  791. * in either case.
  792. * Obviously this works in any row or column. It also works if A == B.
  793. * It doesn't work for the degenerate case:
  794. * ...x A A x x
  795. * ...x B y x x
  796. * where the square marked 'y' isn't necessarily white (consider the left-most A
  797. * is black).
  798. *
  799. * */
  800. static void solve_offsetpair_pair(game_state *state, struct solver_state *ss,
  801. int x1, int y1, int x2, int y2)
  802. {
  803. int ox, oy, w = state->w, ax, ay, an, d, dx[2], dy[2], dn, xd, yd;
  804. if (x1 == x2) { /* same column */
  805. ox = 1; oy = 0;
  806. } else {
  807. assert(y1 == y2);
  808. ox = 0; oy = 1;
  809. }
  810. /* We try adjacent to (x1,y1) and the two diag. adjacent to (x2, y2).
  811. * We expect to be called twice, once each way around. */
  812. ax = x1+ox; ay = y1+oy;
  813. assert(INGRID(state, ax, ay));
  814. an = state->nums[ay*w + ax];
  815. dx[0] = x2 + ox + oy; dx[1] = x2 + ox - oy;
  816. dy[0] = y2 + oy + ox; dy[1] = y2 + oy - ox;
  817. for (d = 0; d < 2; d++) {
  818. if (INGRID(state, dx[d], dy[d]) && (dx[d] != ax || dy[d] != ay)) {
  819. /* The 'dx != ax || dy != ay' removes the degenerate case,
  820. * mentioned above. */
  821. dn = state->nums[dy[d]*w + dx[d]];
  822. if (an == dn) {
  823. /* We have a match; so (WLOG) the 'A' marked above are at
  824. * (x1,y1) and (x2,y2), and the 'B' are at (ax,ay) and (dx,dy). */
  825. debug(("Found offset-pair: %d at (%d,%d) and (%d,%d)\n",
  826. state->nums[y1*w + x1], x1, y1, x2, y2));
  827. debug((" and: %d at (%d,%d) and (%d,%d)\n",
  828. an, ax, ay, dx[d], dy[d]));
  829. xd = dx[d] - x2; yd = dy[d] - y2;
  830. solver_op_add(ss, x2 + xd, y2, CIRCLE, "IP: next to offset-pair");
  831. solver_op_add(ss, x2, y2 + yd, CIRCLE, "IP: next to offset-pair");
  832. }
  833. }
  834. }
  835. }
  836. static int solve_offsetpair(game_state *state, struct solver_state *ss)
  837. {
  838. int n_ops = ss->n_ops, x, xx, y, yy, n1, n2;
  839. for (x = 0; x < state->w-1; x++) {
  840. for (y = 0; y < state->h; y++) {
  841. n1 = state->nums[y*state->w + x];
  842. for (yy = y+1; yy < state->h; yy++) {
  843. n2 = state->nums[yy*state->w + x];
  844. if (n1 == n2) {
  845. solve_offsetpair_pair(state, ss, x, y, x, yy);
  846. solve_offsetpair_pair(state, ss, x, yy, x, y);
  847. }
  848. }
  849. }
  850. }
  851. for (y = 0; y < state->h-1; y++) {
  852. for (x = 0; x < state->w; x++) {
  853. n1 = state->nums[y*state->w + x];
  854. for (xx = x+1; xx < state->w; xx++) {
  855. n2 = state->nums[y*state->w + xx];
  856. if (n1 == n2) {
  857. solve_offsetpair_pair(state, ss, x, y, xx, y);
  858. solve_offsetpair_pair(state, ss, xx, y, x, y);
  859. }
  860. }
  861. }
  862. }
  863. return ss->n_ops - n_ops;
  864. }
  865. static bool solve_hassinglewhiteregion(
  866. game_state *state, struct solver_state *ss)
  867. {
  868. int i, j, nwhite = 0, lwhite = -1, szwhite, start, end, next, a, d, x, y;
  869. for (i = 0; i < state->n; i++) {
  870. if (!(state->flags[i] & F_BLACK)) {
  871. nwhite++;
  872. lwhite = i;
  873. }
  874. state->flags[i] &= ~F_SCRATCH;
  875. }
  876. if (lwhite == -1) {
  877. debug(("solve_hassinglewhite: no white squares found!\n"));
  878. state->impossible = true;
  879. return false;
  880. }
  881. /* We don't use connect_dsf here; it's too slow, and there's a quicker
  882. * algorithm if all we want is the size of one region. */
  883. /* Having written this, this algorithm is only about 5% faster than
  884. * using a dsf. */
  885. memset(ss->scratch, -1, state->n * sizeof(int));
  886. ss->scratch[0] = lwhite;
  887. state->flags[lwhite] |= F_SCRATCH;
  888. start = 0; end = next = 1;
  889. while (start < end) {
  890. for (a = start; a < end; a++) {
  891. i = ss->scratch[a]; assert(i != -1);
  892. for (d = 0; d < 4; d++) {
  893. x = (i % state->w) + dxs[d];
  894. y = (i / state->w) + dys[d];
  895. j = y*state->w + x;
  896. if (!INGRID(state, x, y)) continue;
  897. if (state->flags[j] & (F_BLACK | F_SCRATCH)) continue;
  898. ss->scratch[next++] = j;
  899. state->flags[j] |= F_SCRATCH;
  900. }
  901. }
  902. start = end; end = next;
  903. }
  904. szwhite = next;
  905. return (szwhite == nwhite);
  906. }
  907. static void solve_removesplits_check(game_state *state, struct solver_state *ss,
  908. int x, int y)
  909. {
  910. int i = y*state->w + x;
  911. bool issingle;
  912. if (!INGRID(state, x, y)) return;
  913. if ((state->flags[i] & F_CIRCLE) || (state->flags[i] & F_BLACK))
  914. return;
  915. /* If putting a black square at (x,y) would make the white region
  916. * non-contiguous, it must be circled. */
  917. state->flags[i] |= F_BLACK;
  918. issingle = solve_hassinglewhiteregion(state, ss);
  919. state->flags[i] &= ~F_BLACK;
  920. if (!issingle)
  921. solver_op_add(ss, x, y, CIRCLE, "MC: black square here would split white region");
  922. }
  923. /* For all black squares, search in squares diagonally adjacent to see if
  924. * we can rule out putting a black square there (because it would make the
  925. * white region non-contiguous). */
  926. /* This function is likely to be somewhat slow. */
  927. static int solve_removesplits(game_state *state, struct solver_state *ss)
  928. {
  929. int i, x, y, n_ops = ss->n_ops;
  930. if (!solve_hassinglewhiteregion(state, ss)) {
  931. debug(("solve_removesplits: white region is not contiguous at start!\n"));
  932. state->impossible = true;
  933. return 0;
  934. }
  935. for (i = 0; i < state->n; i++) {
  936. if (!(state->flags[i] & F_BLACK)) continue;
  937. x = i%state->w; y = i/state->w;
  938. solve_removesplits_check(state, ss, x-1, y-1);
  939. solve_removesplits_check(state, ss, x+1, y-1);
  940. solve_removesplits_check(state, ss, x+1, y+1);
  941. solve_removesplits_check(state, ss, x-1, y+1);
  942. }
  943. return ss->n_ops - n_ops;
  944. }
  945. /*
  946. * This function performs a solver step that isn't implicit in the rules
  947. * of the game and is thus treated somewhat differently.
  948. *
  949. * It marks cells whose number does not exist elsewhere in its row/column
  950. * with circles. As it happens the game generator here does mean that this
  951. * is always correct, but it's a solving method that people should not have
  952. * to rely upon (except in the hidden 'sneaky' difficulty setting) and so
  953. * all grids at 'tricky' and above are checked to make sure that the grid
  954. * is no easier if this solving step is performed beforehand.
  955. *
  956. * Calling with ss=NULL just returns the number of sneaky deductions that
  957. * would have been made.
  958. */
  959. static int solve_sneaky(game_state *state, struct solver_state *ss)
  960. {
  961. int i, ii, x, xx, y, yy, nunique = 0;
  962. /* Clear SCRATCH flags. */
  963. for (i = 0; i < state->n; i++) state->flags[i] &= ~F_SCRATCH;
  964. for (x = 0; x < state->w; x++) {
  965. for (y = 0; y < state->h; y++) {
  966. i = y*state->w + x;
  967. /* Check for duplicate numbers on our row, mark (both) if so */
  968. for (xx = x; xx < state->w; xx++) {
  969. ii = y*state->w + xx;
  970. if (i == ii) continue;
  971. if (state->nums[i] == state->nums[ii]) {
  972. state->flags[i] |= F_SCRATCH;
  973. state->flags[ii] |= F_SCRATCH;
  974. }
  975. }
  976. /* Check for duplicate numbers on our col, mark (both) if so */
  977. for (yy = y; yy < state->h; yy++) {
  978. ii = yy*state->w + x;
  979. if (i == ii) continue;
  980. if (state->nums[i] == state->nums[ii]) {
  981. state->flags[i] |= F_SCRATCH;
  982. state->flags[ii] |= F_SCRATCH;
  983. }
  984. }
  985. }
  986. }
  987. /* Any cell with no marking has no duplicates on its row or column:
  988. * set its CIRCLE. */
  989. for (i = 0; i < state->n; i++) {
  990. if (!(state->flags[i] & F_SCRATCH)) {
  991. if (ss) solver_op_add(ss, i%state->w, i/state->w, CIRCLE,
  992. "SNEAKY: only one of its number in row and col");
  993. nunique += 1;
  994. } else
  995. state->flags[i] &= ~F_SCRATCH;
  996. }
  997. return nunique;
  998. }
  999. static int solve_specific(game_state *state, int diff, bool sneaky)
  1000. {
  1001. struct solver_state *ss = solver_state_new(state);
  1002. if (sneaky) solve_sneaky(state, ss);
  1003. /* Some solver operations we only have to perform once --
  1004. * they're only based on the numbers available, and not black
  1005. * squares or circles which may be added later. */
  1006. solve_singlesep(state, ss); /* never sets impossible */
  1007. solve_doubles(state, ss); /* ditto */
  1008. solve_corners(state, ss); /* ditto */
  1009. if (diff >= DIFF_TRICKY)
  1010. solve_offsetpair(state, ss); /* ditto */
  1011. while (1) {
  1012. if (ss->n_ops > 0) solver_ops_do(state, ss);
  1013. if (state->impossible) break;
  1014. if (solve_allblackbutone(state, ss) > 0) continue;
  1015. if (state->impossible) break;
  1016. if (diff >= DIFF_TRICKY) {
  1017. if (solve_removesplits(state, ss) > 0) continue;
  1018. if (state->impossible) break;
  1019. }
  1020. break;
  1021. }
  1022. solver_state_free(ss);
  1023. return state->impossible ? -1 : check_complete(state, CC_MUST_FILL);
  1024. }
  1025. static char *solve_game(const game_state *state, const game_state *currstate,
  1026. const char *aux, const char **error)
  1027. {
  1028. game_state *solved = dup_game(currstate);
  1029. char *move = NULL;
  1030. if (solve_specific(solved, DIFF_ANY, false) > 0) goto solved;
  1031. free_game(solved);
  1032. solved = dup_game(state);
  1033. if (solve_specific(solved, DIFF_ANY, false) > 0) goto solved;
  1034. free_game(solved);
  1035. *error = "Unable to solve puzzle.";
  1036. return NULL;
  1037. solved:
  1038. move = game_state_diff(currstate, solved, true);
  1039. free_game(solved);
  1040. return move;
  1041. }
  1042. /* --- Game generation --- */
  1043. /* A correctly completed Hitori board is essentially a latin square
  1044. * (no duplicated numbers in any row or column) with black squares
  1045. * added such that no black square touches another, and the white
  1046. * squares make a contiguous region.
  1047. *
  1048. * So we can generate it by:
  1049. * constructing a latin square
  1050. * adding black squares at random (minding the constraints)
  1051. * altering the numbers under the new black squares such that
  1052. the solver gets a headstart working out where they are.
  1053. */
  1054. static bool new_game_is_good(const game_params *params,
  1055. game_state *state, game_state *tosolve)
  1056. {
  1057. int sret, sret_easy = 0;
  1058. memcpy(tosolve->nums, state->nums, state->n * sizeof(int));
  1059. memset(tosolve->flags, 0, state->n * sizeof(unsigned int));
  1060. tosolve->completed = false;
  1061. tosolve->impossible = false;
  1062. /*
  1063. * We try and solve it twice, once at our requested difficulty level
  1064. * (ensuring it's soluble at all) and once at the level below (if
  1065. * it exists), which we hope to fail: if you can also solve it at
  1066. * the level below then it's too easy and we have to try again.
  1067. *
  1068. * With this puzzle in particular there's an extra finesse, which is
  1069. * that we check that the generated puzzle isn't too easy _with
  1070. * an extra solver step first_, which is the 'sneaky' mode of deductions
  1071. * (asserting that any number which fulfils the latin-square rules
  1072. * on its row/column must be white). This is an artefact of the
  1073. * generation process and not implicit in the rules, so we don't want
  1074. * people to be able to use it to make the puzzle easier.
  1075. */
  1076. assert(params->diff < DIFF_MAX);
  1077. sret = solve_specific(tosolve, params->diff, false);
  1078. if (params->diff > DIFF_EASY) {
  1079. memset(tosolve->flags, 0, state->n * sizeof(unsigned int));
  1080. tosolve->completed = false;
  1081. tosolve->impossible = false;
  1082. /* this is the only time the 'sneaky' flag is set. */
  1083. sret_easy = solve_specific(tosolve, params->diff-1, true);
  1084. }
  1085. if (sret <= 0 || sret_easy > 0) {
  1086. debug(("Generated puzzle %s at chosen difficulty %s\n",
  1087. sret <= 0 ? "insoluble" : "too easy",
  1088. singles_diffnames[params->diff]));
  1089. return false;
  1090. }
  1091. return true;
  1092. }
  1093. #define MAXTRIES 20
  1094. static int best_black_col(game_state *state, random_state *rs, int *scratch,
  1095. int i, int *rownums, int *colnums)
  1096. {
  1097. int w = state->w, x = i%w, y = i/w, j, o = state->o;
  1098. /* Randomise the list of numbers to try. */
  1099. for (i = 0; i < o; i++) scratch[i] = i;
  1100. shuffle(scratch, o, sizeof(int), rs);
  1101. /* Try each number in turn, first giving preference to removing
  1102. * latin-square characteristics (i.e. those numbers which only
  1103. * occur once in a row/column). The '&&' here, although intuitively
  1104. * wrong, results in a smaller number of 'sneaky' deductions on
  1105. * solvable boards. */
  1106. for (i = 0; i < o; i++) {
  1107. j = scratch[i] + 1;
  1108. if (rownums[y*o + j-1] == 1 && colnums[x*o + j-1] == 1)
  1109. goto found;
  1110. }
  1111. /* Then try each number in turn returning the first one that's
  1112. * not actually unique in its row/column (see comment below) */
  1113. for (i = 0; i < o; i++) {
  1114. j = scratch[i] + 1;
  1115. if (rownums[y*o + j-1] != 0 || colnums[x*o + j-1] != 0)
  1116. goto found;
  1117. }
  1118. assert(!"unable to place number under black cell.");
  1119. return 0;
  1120. found:
  1121. /* Update column and row counts assuming this number will be placed. */
  1122. rownums[y*o + j-1] += 1;
  1123. colnums[x*o + j-1] += 1;
  1124. return j;
  1125. }
  1126. static char *new_game_desc(const game_params *params, random_state *rs,
  1127. char **aux, bool interactive)
  1128. {
  1129. game_state *state = blank_game(params->w, params->h);
  1130. game_state *tosolve = blank_game(params->w, params->h);
  1131. int i, j, *scratch, *rownums, *colnums, x, y, ntries;
  1132. int w = state->w, h = state->h, o = state->o;
  1133. char *ret;
  1134. digit *latin;
  1135. struct solver_state *ss = solver_state_new(state);
  1136. scratch = snewn(state->n, int);
  1137. rownums = snewn(h*o, int);
  1138. colnums = snewn(w*o, int);
  1139. generate:
  1140. ss->n_ops = 0;
  1141. debug(("Starting game generation, size %dx%d\n", w, h));
  1142. memset(state->flags, 0, state->n*sizeof(unsigned int));
  1143. /* First, generate the latin rectangle.
  1144. * The order of this, o, is max(w,h). */
  1145. latin = latin_generate_rect(w, h, rs);
  1146. for (i = 0; i < state->n; i++)
  1147. state->nums[i] = (int)latin[i];
  1148. sfree(latin);
  1149. debug_state("State after latin square", state);
  1150. /* Add black squares at random, using bits of solver as we go (to lay
  1151. * white squares), until we can lay no more blacks. */
  1152. for (i = 0; i < state->n; i++)
  1153. scratch[i] = i;
  1154. shuffle(scratch, state->n, sizeof(int), rs);
  1155. for (j = 0; j < state->n; j++) {
  1156. i = scratch[j];
  1157. if ((state->flags[i] & F_CIRCLE) || (state->flags[i] & F_BLACK)) {
  1158. debug(("generator skipping (%d,%d): %s\n", i%w, i/w,
  1159. (state->flags[i] & F_CIRCLE) ? "CIRCLE" : "BLACK"));
  1160. continue; /* solver knows this must be one or the other already. */
  1161. }
  1162. /* Add a random black cell... */
  1163. solver_op_add(ss, i%w, i/w, BLACK, "Generator: adding random black cell");
  1164. solver_ops_do(state, ss);
  1165. /* ... and do as well as we know how to lay down whites that are now forced. */
  1166. solve_allblackbutone(state, ss);
  1167. solver_ops_do(state, ss);
  1168. solve_removesplits(state, ss);
  1169. solver_ops_do(state, ss);
  1170. if (state->impossible) {
  1171. debug(("generator made impossible, restarting...\n"));
  1172. goto generate;
  1173. }
  1174. }
  1175. debug_state("State after adding blacks", state);
  1176. /* Now we know which squares are white and which are black, we lay numbers
  1177. * under black squares at random, except that the number must appear in
  1178. * white cells at least once more in the same column or row as that [black]
  1179. * square. That's necessary to avoid multiple solutions, where blackening
  1180. * squares in the finished puzzle becomes optional. We use two arrays:
  1181. *
  1182. * rownums[ROW * o + NUM-1] is the no. of white cells containing NUM in y=ROW
  1183. * colnums[COL * o + NUM-1] is the no. of white cells containing NUM in x=COL
  1184. */
  1185. memset(rownums, 0, h*o * sizeof(int));
  1186. memset(colnums, 0, w*o * sizeof(int));
  1187. for (i = 0; i < state->n; i++) {
  1188. if (state->flags[i] & F_BLACK) continue;
  1189. j = state->nums[i];
  1190. x = i%w; y = i/w;
  1191. rownums[y * o + j-1] += 1;
  1192. colnums[x * o + j-1] += 1;
  1193. }
  1194. ntries = 0;
  1195. randomise:
  1196. for (i = 0; i < state->n; i++) {
  1197. if (!(state->flags[i] & F_BLACK)) continue;
  1198. state->nums[i] = best_black_col(state, rs, scratch, i, rownums, colnums);
  1199. }
  1200. debug_state("State after adding numbers", state);
  1201. /* DIFF_ANY just returns whatever we first generated, for testing purposes. */
  1202. if (params->diff != DIFF_ANY &&
  1203. !new_game_is_good(params, state, tosolve)) {
  1204. ntries++;
  1205. if (ntries > MAXTRIES) {
  1206. debug(("Ran out of randomisation attempts, re-generating.\n"));
  1207. goto generate;
  1208. }
  1209. debug(("Re-randomising numbers under black squares.\n"));
  1210. goto randomise;
  1211. }
  1212. ret = generate_desc(state, false);
  1213. free_game(tosolve);
  1214. free_game(state);
  1215. solver_state_free(ss);
  1216. sfree(scratch);
  1217. sfree(rownums);
  1218. sfree(colnums);
  1219. return ret;
  1220. }
  1221. static const char *validate_desc(const game_params *params, const char *desc)
  1222. {
  1223. const char *ret = NULL;
  1224. unpick_desc(params, desc, NULL, &ret);
  1225. return ret;
  1226. }
  1227. static game_state *new_game(midend *me, const game_params *params,
  1228. const char *desc)
  1229. {
  1230. game_state *state = NULL;
  1231. unpick_desc(params, desc, &state, NULL);
  1232. if (!state) assert(!"new_game failed to unpick");
  1233. return state;
  1234. }
  1235. /* --- Game UI and move routines --- */
  1236. struct game_ui {
  1237. int cx, cy;
  1238. bool cshow, show_black_nums;
  1239. };
  1240. static game_ui *new_ui(const game_state *state)
  1241. {
  1242. game_ui *ui = snew(game_ui);
  1243. ui->cx = ui->cy = 0;
  1244. ui->cshow = getenv_bool("PUZZLES_SHOW_CURSOR", false);
  1245. ui->show_black_nums = false;
  1246. return ui;
  1247. }
  1248. static void free_ui(game_ui *ui)
  1249. {
  1250. sfree(ui);
  1251. }
  1252. static void game_changed_state(game_ui *ui, const game_state *oldstate,
  1253. const game_state *newstate)
  1254. {
  1255. if (!oldstate->completed && newstate->completed)
  1256. ui->cshow = false;
  1257. }
  1258. static const char *current_key_label(const game_ui *ui,
  1259. const game_state *state, int button)
  1260. {
  1261. if (IS_CURSOR_SELECT(button) && ui->cshow) {
  1262. unsigned int f = state->flags[ui->cy * state->w + ui->cx];
  1263. if (f & F_BLACK) return "Restore";
  1264. if (f & F_CIRCLE) return "Remove";
  1265. return button == CURSOR_SELECT ? "Black" : "Circle";
  1266. }
  1267. return "";
  1268. }
  1269. #define DS_BLACK 0x1
  1270. #define DS_CIRCLE 0x2
  1271. #define DS_CURSOR 0x4
  1272. #define DS_BLACK_NUM 0x8
  1273. #define DS_ERROR 0x10
  1274. #define DS_FLASH 0x20
  1275. #define DS_IMPOSSIBLE 0x40
  1276. struct game_drawstate {
  1277. int tilesize;
  1278. bool started, solved;
  1279. int w, h, n;
  1280. unsigned int *flags;
  1281. };
  1282. static char *interpret_move(const game_state *state, game_ui *ui,
  1283. const game_drawstate *ds,
  1284. int mx, int my, int button)
  1285. {
  1286. char buf[80], c;
  1287. int i, x = FROMCOORD(mx), y = FROMCOORD(my);
  1288. enum { NONE, TOGGLE_BLACK, TOGGLE_CIRCLE, UI } action = NONE;
  1289. if (IS_CURSOR_MOVE(button)) {
  1290. move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, true);
  1291. ui->cshow = true;
  1292. action = UI;
  1293. } else if (IS_CURSOR_SELECT(button)) {
  1294. x = ui->cx; y = ui->cy;
  1295. if (!ui->cshow) {
  1296. action = UI;
  1297. ui->cshow = true;
  1298. }
  1299. if (button == CURSOR_SELECT) {
  1300. action = TOGGLE_BLACK;
  1301. } else if (button == CURSOR_SELECT2) {
  1302. action = TOGGLE_CIRCLE;
  1303. }
  1304. } else if (IS_MOUSE_DOWN(button)) {
  1305. if (ui->cshow) {
  1306. ui->cshow = false;
  1307. action = UI;
  1308. }
  1309. if (!INGRID(state, x, y)) {
  1310. ui->show_black_nums = !ui->show_black_nums;
  1311. action = UI; /* this wants to be a per-game option. */
  1312. } else if (button == LEFT_BUTTON) {
  1313. action = TOGGLE_BLACK;
  1314. } else if (button == RIGHT_BUTTON) {
  1315. action = TOGGLE_CIRCLE;
  1316. }
  1317. }
  1318. if (action == UI) return MOVE_UI_UPDATE;
  1319. if (action == TOGGLE_BLACK || action == TOGGLE_CIRCLE) {
  1320. i = y * state->w + x;
  1321. if (state->flags[i] & (F_BLACK | F_CIRCLE))
  1322. c = 'E';
  1323. else
  1324. c = (action == TOGGLE_BLACK) ? 'B' : 'C';
  1325. sprintf(buf, "%c%d,%d", (int)c, x, y);
  1326. return dupstr(buf);
  1327. }
  1328. return NULL;
  1329. }
  1330. static game_state *execute_move(const game_state *state, const char *move)
  1331. {
  1332. game_state *ret = dup_game(state);
  1333. int x, y, i, n;
  1334. debug(("move: %s\n", move));
  1335. while (*move) {
  1336. char c = *move;
  1337. if (c == 'B' || c == 'C' || c == 'E') {
  1338. move++;
  1339. if (sscanf(move, "%d,%d%n", &x, &y, &n) != 2 ||
  1340. !INGRID(state, x, y))
  1341. goto badmove;
  1342. i = y*ret->w + x;
  1343. ret->flags[i] &= ~(F_CIRCLE | F_BLACK); /* empty first, always. */
  1344. if (c == 'B')
  1345. ret->flags[i] |= F_BLACK;
  1346. else if (c == 'C')
  1347. ret->flags[i] |= F_CIRCLE;
  1348. move += n;
  1349. } else if (c == 'S') {
  1350. move++;
  1351. ret->used_solve = true;
  1352. } else
  1353. goto badmove;
  1354. if (*move == ';')
  1355. move++;
  1356. else if (*move)
  1357. goto badmove;
  1358. }
  1359. if (check_complete(ret, CC_MARK_ERRORS)) ret->completed = true;
  1360. return ret;
  1361. badmove:
  1362. free_game(ret);
  1363. return NULL;
  1364. }
  1365. /* ----------------------------------------------------------------------
  1366. * Drawing routines.
  1367. */
  1368. static void game_compute_size(const game_params *params, int tilesize,
  1369. const game_ui *ui, int *x, int *y)
  1370. {
  1371. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  1372. struct { int tilesize; } ads, *ds = &ads;
  1373. ads.tilesize = tilesize;
  1374. *x = TILE_SIZE * params->w + 2 * BORDER;
  1375. *y = TILE_SIZE * params->h + 2 * BORDER;
  1376. }
  1377. static void game_set_size(drawing *dr, game_drawstate *ds,
  1378. const game_params *params, int tilesize)
  1379. {
  1380. ds->tilesize = tilesize;
  1381. }
  1382. static float *game_colours(frontend *fe, int *ncolours)
  1383. {
  1384. float *ret = snewn(3 * NCOLOURS, float);
  1385. int i;
  1386. game_mkhighlight(fe, ret, COL_BACKGROUND, -1, COL_LOWLIGHT);
  1387. for (i = 0; i < 3; i++) {
  1388. ret[COL_BLACK * 3 + i] = 0.0F;
  1389. ret[COL_BLACKNUM * 3 + i] = 0.4F;
  1390. ret[COL_WHITE * 3 + i] = 1.0F;
  1391. ret[COL_GRID * 3 + i] = ret[COL_LOWLIGHT * 3 + i];
  1392. ret[COL_UNUSED1 * 3 + i] = 0.0F; /* To placate an assertion. */
  1393. }
  1394. ret[COL_CURSOR * 3 + 0] = 0.2F;
  1395. ret[COL_CURSOR * 3 + 1] = 0.8F;
  1396. ret[COL_CURSOR * 3 + 2] = 0.0F;
  1397. ret[COL_ERROR * 3 + 0] = 1.0F;
  1398. ret[COL_ERROR * 3 + 1] = 0.0F;
  1399. ret[COL_ERROR * 3 + 2] = 0.0F;
  1400. *ncolours = NCOLOURS;
  1401. return ret;
  1402. }
  1403. static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
  1404. {
  1405. struct game_drawstate *ds = snew(struct game_drawstate);
  1406. ds->tilesize = 0;
  1407. ds->started = false;
  1408. ds->solved = false;
  1409. ds->w = state->w;
  1410. ds->h = state->h;
  1411. ds->n = state->n;
  1412. ds->flags = snewn(state->n, unsigned int);
  1413. memset(ds->flags, 0, state->n*sizeof(unsigned int));
  1414. return ds;
  1415. }
  1416. static void game_free_drawstate(drawing *dr, game_drawstate *ds)
  1417. {
  1418. sfree(ds->flags);
  1419. sfree(ds);
  1420. }
  1421. static void tile_redraw(drawing *dr, game_drawstate *ds, int x, int y,
  1422. int num, unsigned int f)
  1423. {
  1424. int tcol, bg, cx, cy, tsz;
  1425. bool dnum;
  1426. char buf[32];
  1427. if (f & DS_BLACK) {
  1428. bg = (f & DS_ERROR) ? COL_ERROR : COL_BLACK;
  1429. tcol = COL_BLACKNUM;
  1430. dnum = (f & DS_BLACK_NUM);
  1431. } else {
  1432. bg = (f & DS_FLASH) ? COL_LOWLIGHT : COL_BACKGROUND;
  1433. tcol = (f & DS_ERROR) ? COL_ERROR : COL_BLACK;
  1434. dnum = true;
  1435. }
  1436. cx = x + TILE_SIZE/2; cy = y + TILE_SIZE/2;
  1437. draw_rect(dr, x, y, TILE_SIZE, TILE_SIZE, bg);
  1438. draw_rect_outline(dr, x, y, TILE_SIZE, TILE_SIZE,
  1439. (f & DS_IMPOSSIBLE) ? COL_ERROR : COL_GRID);
  1440. if (f & DS_CIRCLE) {
  1441. draw_circle(dr, cx, cy, CRAD, tcol, tcol);
  1442. draw_circle(dr, cx, cy, CRAD-1, bg, tcol);
  1443. }
  1444. if (dnum) {
  1445. sprintf(buf, "%d", num);
  1446. if (strlen(buf) == 1)
  1447. tsz = TEXTSZ;
  1448. else
  1449. tsz = (CRAD*2 - 1) / strlen(buf);
  1450. draw_text(dr, cx, cy, FONT_VARIABLE, tsz,
  1451. ALIGN_VCENTRE | ALIGN_HCENTRE, tcol, buf);
  1452. }
  1453. if (f & DS_CURSOR)
  1454. draw_rect_corners(dr, cx, cy, TEXTSZ/2, COL_CURSOR);
  1455. draw_update(dr, x, y, TILE_SIZE, TILE_SIZE);
  1456. }
  1457. static void game_redraw(drawing *dr, game_drawstate *ds,
  1458. const game_state *oldstate, const game_state *state,
  1459. int dir, const game_ui *ui,
  1460. float animtime, float flashtime)
  1461. {
  1462. int x, y, i, flash;
  1463. unsigned int f;
  1464. flash = (int)(flashtime * 5 / FLASH_TIME) % 2;
  1465. if (!ds->started) {
  1466. int wsz = TILE_SIZE * state->w + 2 * BORDER;
  1467. int hsz = TILE_SIZE * state->h + 2 * BORDER;
  1468. draw_rect_outline(dr, COORD(0)-1, COORD(0)-1,
  1469. TILE_SIZE * state->w + 2, TILE_SIZE * state->h + 2,
  1470. COL_GRID);
  1471. draw_update(dr, 0, 0, wsz, hsz);
  1472. }
  1473. for (x = 0; x < state->w; x++) {
  1474. for (y = 0; y < state->h; y++) {
  1475. i = y*state->w + x;
  1476. f = 0;
  1477. if (flash) f |= DS_FLASH;
  1478. if (state->impossible) f |= DS_IMPOSSIBLE;
  1479. if (ui->cshow && x == ui->cx && y == ui->cy)
  1480. f |= DS_CURSOR;
  1481. if (state->flags[i] & F_BLACK) {
  1482. f |= DS_BLACK;
  1483. if (ui->show_black_nums) f |= DS_BLACK_NUM;
  1484. }
  1485. if (state->flags[i] & F_CIRCLE)
  1486. f |= DS_CIRCLE;
  1487. if (state->flags[i] & F_ERROR)
  1488. f |= DS_ERROR;
  1489. if (!ds->started || ds->flags[i] != f) {
  1490. tile_redraw(dr, ds, COORD(x), COORD(y),
  1491. state->nums[i], f);
  1492. ds->flags[i] = f;
  1493. }
  1494. }
  1495. }
  1496. ds->started = true;
  1497. }
  1498. static float game_anim_length(const game_state *oldstate,
  1499. const game_state *newstate, int dir, game_ui *ui)
  1500. {
  1501. return 0.0F;
  1502. }
  1503. static float game_flash_length(const game_state *oldstate,
  1504. const game_state *newstate, int dir, game_ui *ui)
  1505. {
  1506. if (!oldstate->completed &&
  1507. newstate->completed && !newstate->used_solve)
  1508. return FLASH_TIME;
  1509. return 0.0F;
  1510. }
  1511. static void game_get_cursor_location(const game_ui *ui,
  1512. const game_drawstate *ds,
  1513. const game_state *state,
  1514. const game_params *params,
  1515. int *x, int *y, int *w, int *h)
  1516. {
  1517. if(ui->cshow) {
  1518. *x = COORD(ui->cx);
  1519. *y = COORD(ui->cy);
  1520. *w = *h = TILE_SIZE;
  1521. }
  1522. }
  1523. static int game_status(const game_state *state)
  1524. {
  1525. return state->completed ? +1 : 0;
  1526. }
  1527. static void game_print_size(const game_params *params, const game_ui *ui,
  1528. float *x, float *y)
  1529. {
  1530. int pw, ph;
  1531. /* 8mm squares by default. */
  1532. game_compute_size(params, 800, ui, &pw, &ph);
  1533. *x = pw / 100.0F;
  1534. *y = ph / 100.0F;
  1535. }
  1536. static void game_print(drawing *dr, const game_state *state, const game_ui *ui,
  1537. int tilesize)
  1538. {
  1539. int ink = print_mono_colour(dr, 0);
  1540. int paper = print_mono_colour(dr, 1);
  1541. int x, y, ox, oy, i;
  1542. char buf[32];
  1543. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  1544. game_drawstate ads, *ds = &ads;
  1545. game_set_size(dr, ds, NULL, tilesize);
  1546. print_line_width(dr, 2 * TILE_SIZE / 40);
  1547. for (x = 0; x < state->w; x++) {
  1548. for (y = 0; y < state->h; y++) {
  1549. ox = COORD(x); oy = COORD(y);
  1550. i = y*state->w+x;
  1551. if (state->flags[i] & F_BLACK) {
  1552. draw_rect(dr, ox, oy, TILE_SIZE, TILE_SIZE, ink);
  1553. } else {
  1554. draw_rect_outline(dr, ox, oy, TILE_SIZE, TILE_SIZE, ink);
  1555. if (state->flags[i] & DS_CIRCLE)
  1556. draw_circle(dr, ox+TILE_SIZE/2, oy+TILE_SIZE/2, CRAD,
  1557. paper, ink);
  1558. sprintf(buf, "%d", state->nums[i]);
  1559. draw_text(dr, ox+TILE_SIZE/2, oy+TILE_SIZE/2, FONT_VARIABLE,
  1560. TEXTSZ/strlen(buf), ALIGN_VCENTRE | ALIGN_HCENTRE,
  1561. ink, buf);
  1562. }
  1563. }
  1564. }
  1565. }
  1566. #ifdef COMBINED
  1567. #define thegame singles
  1568. #endif
  1569. const struct game thegame = {
  1570. "Singles", "games.singles", "singles",
  1571. default_params,
  1572. game_fetch_preset, NULL,
  1573. decode_params,
  1574. encode_params,
  1575. free_params,
  1576. dup_params,
  1577. true, game_configure, custom_params,
  1578. validate_params,
  1579. new_game_desc,
  1580. validate_desc,
  1581. new_game,
  1582. dup_game,
  1583. free_game,
  1584. true, solve_game,
  1585. true, game_can_format_as_text_now, game_text_format,
  1586. NULL, NULL, /* get_prefs, set_prefs */
  1587. new_ui,
  1588. free_ui,
  1589. NULL, /* encode_ui */
  1590. NULL, /* decode_ui */
  1591. NULL, /* game_request_keys */
  1592. game_changed_state,
  1593. current_key_label,
  1594. interpret_move,
  1595. execute_move,
  1596. PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
  1597. game_colours,
  1598. game_new_drawstate,
  1599. game_free_drawstate,
  1600. game_redraw,
  1601. game_anim_length,
  1602. game_flash_length,
  1603. game_get_cursor_location,
  1604. game_status,
  1605. true, false, game_print_size, game_print,
  1606. false, /* wants_statusbar */
  1607. false, NULL, /* timing_state */
  1608. REQUIRE_RBUTTON, /* flags */
  1609. };
  1610. #ifdef STANDALONE_SOLVER
  1611. #include <time.h>
  1612. #include <stdarg.h>
  1613. static void start_soak(game_params *p, random_state *rs)
  1614. {
  1615. time_t tt_start, tt_now, tt_last;
  1616. char *desc, *aux;
  1617. game_state *s;
  1618. int i, n = 0, ndiff[DIFF_MAX], diff, sret, nblack = 0, nsneaky = 0;
  1619. tt_start = tt_now = time(NULL);
  1620. printf("Soak-testing a %dx%d grid.\n", p->w, p->h);
  1621. p->diff = DIFF_ANY;
  1622. memset(ndiff, 0, DIFF_MAX * sizeof(int));
  1623. while (1) {
  1624. n++;
  1625. desc = new_game_desc(p, rs, &aux, false);
  1626. s = new_game(NULL, p, desc);
  1627. nsneaky += solve_sneaky(s, NULL);
  1628. for (diff = 0; diff < DIFF_MAX; diff++) {
  1629. memset(s->flags, 0, s->n * sizeof(unsigned int));
  1630. s->completed = false;
  1631. s->impossible = false;
  1632. sret = solve_specific(s, diff, false);
  1633. if (sret > 0) {
  1634. ndiff[diff]++;
  1635. break;
  1636. } else if (sret < 0)
  1637. fprintf(stderr, "Impossible! %s\n", desc);
  1638. }
  1639. for (i = 0; i < s->n; i++) {
  1640. if (s->flags[i] & F_BLACK) nblack++;
  1641. }
  1642. free_game(s);
  1643. sfree(desc);
  1644. tt_last = time(NULL);
  1645. if (tt_last > tt_now) {
  1646. tt_now = tt_last;
  1647. printf("%d total, %3.1f/s, bl/sn %3.1f%%/%3.1f%%: ",
  1648. n, (double)n / ((double)tt_now - tt_start),
  1649. ((double)nblack * 100.0) / (double)(n * p->w * p->h),
  1650. ((double)nsneaky * 100.0) / (double)(n * p->w * p->h));
  1651. for (diff = 0; diff < DIFF_MAX; diff++) {
  1652. if (diff > 0) printf(", ");
  1653. printf("%d (%3.1f%%) %s",
  1654. ndiff[diff], (double)ndiff[diff] * 100.0 / (double)n,
  1655. singles_diffnames[diff]);
  1656. }
  1657. printf("\n");
  1658. }
  1659. }
  1660. }
  1661. int main(int argc, char **argv)
  1662. {
  1663. char *id = NULL, *desc, *desc_gen = NULL, *tgame, *aux;
  1664. const char *err;
  1665. game_state *s = NULL;
  1666. game_params *p = NULL;
  1667. int soln, ret = 1;
  1668. bool soak = false;
  1669. time_t seed = time(NULL);
  1670. random_state *rs = NULL;
  1671. setvbuf(stdout, NULL, _IONBF, 0);
  1672. while (--argc > 0) {
  1673. char *p = *++argv;
  1674. if (!strcmp(p, "-v")) {
  1675. verbose = true;
  1676. } else if (!strcmp(p, "--soak")) {
  1677. soak = true;
  1678. } else if (!strcmp(p, "--seed")) {
  1679. if (argc == 0) {
  1680. fprintf(stderr, "%s: --seed needs an argument", argv[0]);
  1681. goto done;
  1682. }
  1683. seed = (time_t)atoi(*++argv);
  1684. argc--;
  1685. } else if (*p == '-') {
  1686. fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
  1687. return 1;
  1688. } else {
  1689. id = p;
  1690. }
  1691. }
  1692. rs = random_new((void*)&seed, sizeof(time_t));
  1693. if (!id) {
  1694. fprintf(stderr, "usage: %s [-v] [--soak] <params> | <game_id>\n", argv[0]);
  1695. goto done;
  1696. }
  1697. desc = strchr(id, ':');
  1698. if (desc) *desc++ = '\0';
  1699. p = default_params();
  1700. decode_params(p, id);
  1701. err = validate_params(p, true);
  1702. if (err) {
  1703. fprintf(stderr, "%s: %s", argv[0], err);
  1704. goto done;
  1705. }
  1706. if (soak) {
  1707. if (desc) {
  1708. fprintf(stderr, "%s: --soak only needs params, not game desc.\n", argv[0]);
  1709. goto done;
  1710. }
  1711. start_soak(p, rs);
  1712. } else {
  1713. if (!desc) desc = desc_gen = new_game_desc(p, rs, &aux, false);
  1714. err = validate_desc(p, desc);
  1715. if (err) {
  1716. fprintf(stderr, "%s: %s\n", argv[0], err);
  1717. free_params(p);
  1718. goto done;
  1719. }
  1720. s = new_game(NULL, p, desc);
  1721. if (verbose) {
  1722. tgame = game_text_format(s);
  1723. fputs(tgame, stdout);
  1724. sfree(tgame);
  1725. }
  1726. soln = solve_specific(s, DIFF_ANY, false);
  1727. tgame = game_text_format(s);
  1728. fputs(tgame, stdout);
  1729. sfree(tgame);
  1730. printf("Game was %s.\n\n",
  1731. soln < 0 ? "impossible" : soln > 0 ? "solved" : "not solved");
  1732. }
  1733. ret = 0;
  1734. done:
  1735. if (desc_gen) sfree(desc_gen);
  1736. if (p) free_params(p);
  1737. if (s) free_game(s);
  1738. if (rs) random_free(rs);
  1739. return ret;
  1740. }
  1741. #endif
  1742. /* vim: set shiftwidth=4 tabstop=8: */