tracks.c 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159
  1. /*
  2. * Implementation of 'Train Tracks', a puzzle from the Times on Saturday.
  3. *
  4. * "Lay tracks to enable the train to travel from village A to village B.
  5. * The numbers indicate how many sections of rail go in each row and
  6. * column. There are only straight rails and curved rails. The track
  7. * cannot cross itself."
  8. *
  9. * Puzzles:
  10. * #9 8x8:d9s5c6zgAa,1,4,1,4,4,3,S3,5,2,2,4,S5,3,3,5,1
  11. * #112 8x8:w6x5mAa,1,3,1,4,6,4,S4,3,3,4,5,2,4,2,S5,1
  12. * #113 8x8:gCx5xAf,1,S4,2,5,4,6,2,3,4,2,5,2,S4,4,5,1
  13. * #114 8x8:p5fAzkAb,1,6,3,3,3,S6,2,3,5,4,S3,3,5,1,5,1
  14. * #115 8x8:zi9d5tAb,1,3,4,5,3,S4,2,4,2,6,2,3,6,S3,3,1
  15. * #942 8x8:n5iCfAzAe,2,2,S5,5,3,5,4,5,4,5,2,S5,3,4,5,3
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <assert.h>
  21. #include <ctype.h>
  22. #include <limits.h>
  23. #ifdef NO_TGMATH_H
  24. # include <math.h>
  25. #else
  26. # include <tgmath.h>
  27. #endif
  28. #include "puzzles.h"
  29. /* --- Game parameters --- */
  30. /*
  31. * Difficulty levels. I do some macro ickery here to ensure that my
  32. * enum and the various forms of my name list always match up.
  33. */
  34. #define DIFFLIST(A) \
  35. A(EASY,Easy,e) \
  36. A(TRICKY,Tricky,t) \
  37. A(HARD,Hard,h) \
  38. /* end of list */
  39. #define ENUM(upper,title,lower) DIFF_ ## upper,
  40. #define TITLE(upper,title,lower) #title,
  41. #define ENCODE(upper,title,lower) #lower
  42. #define CONFIG(upper,title,lower) ":" #title
  43. enum { DIFFLIST(ENUM) DIFFCOUNT };
  44. static char const *const tracks_diffnames[] = { DIFFLIST(TITLE) };
  45. static char const tracks_diffchars[] = DIFFLIST(ENCODE);
  46. #define DIFFCONFIG DIFFLIST(CONFIG)
  47. struct game_params {
  48. int w, h, diff;
  49. bool single_ones;
  50. };
  51. static game_params *default_params(void)
  52. {
  53. game_params *ret = snew(game_params);
  54. ret->w = ret->h = 8;
  55. ret->diff = DIFF_TRICKY;
  56. ret->single_ones = true;
  57. return ret;
  58. }
  59. static const struct game_params tracks_presets[] = {
  60. {8, 8, DIFF_EASY, 1},
  61. {8, 8, DIFF_TRICKY, 1},
  62. {10, 8, DIFF_EASY, 1},
  63. {10, 8, DIFF_TRICKY, 1 },
  64. {10, 10, DIFF_EASY, 1},
  65. {10, 10, DIFF_TRICKY, 1},
  66. {10, 10, DIFF_HARD, 1},
  67. {15, 10, DIFF_EASY, 1},
  68. {15, 10, DIFF_TRICKY, 1},
  69. {15, 15, DIFF_EASY, 1},
  70. {15, 15, DIFF_TRICKY, 1},
  71. {15, 15, DIFF_HARD, 1},
  72. };
  73. static bool game_fetch_preset(int i, char **name, game_params **params)
  74. {
  75. game_params *ret;
  76. char str[80];
  77. if (i < 0 || i >= lenof(tracks_presets))
  78. return false;
  79. ret = snew(game_params);
  80. *ret = tracks_presets[i];
  81. sprintf(str, "%dx%d %s", ret->w, ret->h, tracks_diffnames[ret->diff]);
  82. *name = dupstr(str);
  83. *params = ret;
  84. return true;
  85. }
  86. static void free_params(game_params *params)
  87. {
  88. sfree(params);
  89. }
  90. static game_params *dup_params(const game_params *params)
  91. {
  92. game_params *ret = snew(game_params);
  93. *ret = *params; /* structure copy */
  94. return ret;
  95. }
  96. static void decode_params(game_params *params, char const *string)
  97. {
  98. params->w = params->h = atoi(string);
  99. while (*string && isdigit((unsigned char)*string)) string++;
  100. if (*string == 'x') {
  101. string++;
  102. params->h = atoi(string);
  103. while (*string && isdigit((unsigned char)*string)) string++;
  104. }
  105. if (*string == 'd') {
  106. int i;
  107. string++;
  108. params->diff = DIFF_TRICKY;
  109. for (i = 0; i < DIFFCOUNT; i++)
  110. if (*string == tracks_diffchars[i])
  111. params->diff = i;
  112. if (*string) string++;
  113. }
  114. params->single_ones = true;
  115. if (*string == 'o') {
  116. params->single_ones = false;
  117. string++;
  118. }
  119. }
  120. static char *encode_params(const game_params *params, bool full)
  121. {
  122. char buf[120];
  123. sprintf(buf, "%dx%d", params->w, params->h);
  124. if (full)
  125. sprintf(buf + strlen(buf), "d%c%s",
  126. tracks_diffchars[params->diff],
  127. params->single_ones ? "" : "o");
  128. return dupstr(buf);
  129. }
  130. static config_item *game_configure(const game_params *params)
  131. {
  132. config_item *ret;
  133. char buf[80];
  134. ret = snewn(5, config_item);
  135. ret[0].name = "Width";
  136. ret[0].type = C_STRING;
  137. sprintf(buf, "%d", params->w);
  138. ret[0].u.string.sval = dupstr(buf);
  139. ret[1].name = "Height";
  140. ret[1].type = C_STRING;
  141. sprintf(buf, "%d", params->h);
  142. ret[1].u.string.sval = dupstr(buf);
  143. ret[2].name = "Difficulty";
  144. ret[2].type = C_CHOICES;
  145. ret[2].u.choices.choicenames = DIFFCONFIG;
  146. ret[2].u.choices.selected = params->diff;
  147. ret[3].name = "Disallow consecutive 1 clues";
  148. ret[3].type = C_BOOLEAN;
  149. ret[3].u.boolean.bval = params->single_ones;
  150. ret[4].name = NULL;
  151. ret[4].type = C_END;
  152. return ret;
  153. }
  154. static game_params *custom_params(const config_item *cfg)
  155. {
  156. game_params *ret = snew(game_params);
  157. ret->w = atoi(cfg[0].u.string.sval);
  158. ret->h = atoi(cfg[1].u.string.sval);
  159. ret->diff = cfg[2].u.choices.selected;
  160. ret->single_ones = cfg[3].u.boolean.bval;
  161. return ret;
  162. }
  163. static const char *validate_params(const game_params *params, bool full)
  164. {
  165. /*
  166. * Generating anything under 4x4 runs into trouble of one kind
  167. * or another.
  168. */
  169. if (params->w < 4 || params->h < 4)
  170. return "Width and height must both be at least four";
  171. if (params->w > INT_MAX / params->h)
  172. return "Width times height must not be unreasonably large";
  173. return NULL;
  174. }
  175. /* --- Game state --- */
  176. /* flag usage copied from pearl */
  177. #define R 1
  178. #define U 2
  179. #define L 4
  180. #define D 8
  181. #define MOVECHAR(m) ((m==R)?'R':(m==U)?'U':(m==L)?'L':(m==D)?'D':'?')
  182. #define DX(d) ( ((d)==R) - ((d)==L) )
  183. #define DY(d) ( ((d)==D) - ((d)==U) )
  184. #define F(d) (((d << 2) | (d >> 2)) & 0xF)
  185. #define C(d) (((d << 3) | (d >> 1)) & 0xF)
  186. #define A(d) (((d << 1) | (d >> 3)) & 0xF)
  187. #define LR (L | R)
  188. #define RL (R | L)
  189. #define UD (U | D)
  190. #define DU (D | U)
  191. #define LU (L | U)
  192. #define UL (U | L)
  193. #define LD (L | D)
  194. #define DL (D | L)
  195. #define RU (R | U)
  196. #define UR (U | R)
  197. #define RD (R | D)
  198. #define DR (D | R)
  199. #define ALLDIR 15
  200. #define BLANK 0
  201. #define UNKNOWN 15
  202. static const int nbits[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
  203. /* square grid flags */
  204. #define S_TRACK 1 /* a track passes through this square (--> 2 edges) */
  205. #define S_NOTRACK 2 /* no track passes through this square */
  206. #define S_ERROR 4
  207. #define S_CLUE 8
  208. #define S_MARK 16
  209. #define S_FLASH_SHIFT 8 /* Position of tile in solved track */
  210. #define S_FLASH_WIDTH 8 /* Width of above sub-field */
  211. #define S_FLASH_MASK ((1 << S_FLASH_WIDTH) - 1)
  212. #define S_TRACK_SHIFT 16 /* U/D/L/R flags for edge track indicators */
  213. #define S_NOTRACK_SHIFT 20 /* U/D/L/R flags for edge no-track indicators */
  214. /* edge grid flags */
  215. #define E_TRACK 1 /* a track passes through this edge */
  216. #define E_NOTRACK 2 /* no track passes through this edge */
  217. struct numbers {
  218. int refcount;
  219. int *numbers; /* sz w+h */
  220. int row_s, col_s; /* stations: TODO think about multiple lines
  221. (for bigger grids)? */
  222. };
  223. #define INGRID(state, gx, gy) ((gx) >= 0 && (gx) < (state)->p.w && \
  224. (gy) >= 0 && (gy) < (state)->p.h)
  225. struct game_state {
  226. game_params p;
  227. unsigned int *sflags; /* size w*h */
  228. struct numbers *numbers;
  229. int *num_errors; /* size w+h */
  230. bool completed, used_solve, impossible;
  231. };
  232. /* Return the four directions in which a particular edge flag is set, around a square. */
  233. static int S_E_DIRS(const game_state *state, int sx, int sy,
  234. unsigned int eflag) {
  235. return (state->sflags[sy*state->p.w+sx] >>
  236. ((eflag == E_TRACK) ? S_TRACK_SHIFT : S_NOTRACK_SHIFT)) & ALLDIR;
  237. }
  238. /* Count the number of a particular edge flag around a grid square. */
  239. static int S_E_COUNT(const game_state *state, int sx, int sy,
  240. unsigned int eflag) {
  241. return nbits[S_E_DIRS(state, sx, sy, eflag)];
  242. }
  243. /* Return the two flags (E_TRACK and/or E_NOTRACK) set on a specific
  244. * edge of a square. */
  245. static unsigned S_E_FLAGS(const game_state *state, int sx, int sy, int d) {
  246. unsigned f = state->sflags[sy*state->p.w+sx];
  247. int t = (f & (d << S_TRACK_SHIFT)), nt = (f & (d << S_NOTRACK_SHIFT));
  248. return (t ? E_TRACK : 0) | (nt ? E_NOTRACK : 0);
  249. }
  250. static bool S_E_ADJ(const game_state *state, int sx, int sy, int d, int *ax,
  251. int *ay, unsigned int *ad) {
  252. if (d == L && sx > 0) { *ax = sx-1; *ay = sy; *ad = R; return true; }
  253. if (d == R && sx < state->p.w-1) { *ax = sx+1; *ay = sy; *ad = L; return true; }
  254. if (d == U && sy > 0) { *ax = sx; *ay = sy-1; *ad = D; return true; }
  255. if (d == D && sy < state->p.h-1) { *ax = sx; *ay = sy+1; *ad = U; return true; }
  256. return false;
  257. }
  258. /* Sets flag (E_TRACK or E_NOTRACK) on a given edge of a square. */
  259. static void S_E_SET(game_state *state, int sx, int sy, int d,
  260. unsigned int eflag) {
  261. unsigned shift = (eflag == E_TRACK) ? S_TRACK_SHIFT : S_NOTRACK_SHIFT, ad;
  262. int ax, ay;
  263. state->sflags[sy*state->p.w+sx] |= (d << shift);
  264. if (S_E_ADJ(state, sx, sy, d, &ax, &ay, &ad)) {
  265. state->sflags[ay*state->p.w+ax] |= (ad << shift);
  266. }
  267. }
  268. /* Clears flag (E_TRACK or E_NOTRACK) on a given edge of a square. */
  269. static void S_E_CLEAR(game_state *state, int sx, int sy, int d,
  270. unsigned int eflag) {
  271. unsigned shift = (eflag == E_TRACK) ? S_TRACK_SHIFT : S_NOTRACK_SHIFT, ad;
  272. int ax, ay;
  273. state->sflags[sy*state->p.w+sx] &= ~(d << shift);
  274. if (S_E_ADJ(state, sx, sy, d, &ax, &ay, &ad)) {
  275. state->sflags[ay*state->p.w+ax] &= ~(ad << shift);
  276. }
  277. }
  278. static void clear_game(game_state *state)
  279. {
  280. int w = state->p.w, h = state->p.h;
  281. memset(state->sflags, 0, w*h * sizeof(unsigned int));
  282. memset(state->numbers->numbers, 0, (w+h) * sizeof(int));
  283. state->numbers->col_s = state->numbers->row_s = -1;
  284. memset(state->num_errors, 0, (w+h) * sizeof(int));
  285. state->completed = state->used_solve = state->impossible = false;
  286. }
  287. static game_state *blank_game(const game_params *params)
  288. {
  289. game_state *state = snew(game_state);
  290. int w = params->w, h = params->h;
  291. state->p = *params;
  292. state->sflags = snewn(w*h, unsigned int);
  293. state->numbers = snew(struct numbers);
  294. state->numbers->refcount = 1;
  295. state->numbers->numbers = snewn(w+h, int);
  296. state->num_errors = snewn(w+h, int);
  297. clear_game(state);
  298. return state;
  299. }
  300. static void copy_game_flags(const game_state *src, game_state *dest)
  301. {
  302. int w = src->p.w, h = src->p.h;
  303. memcpy(dest->sflags, src->sflags, w*h*sizeof(unsigned int));
  304. }
  305. static game_state *dup_game(const game_state *state)
  306. {
  307. int w = state->p.w, h = state->p.h;
  308. game_state *ret = snew(game_state);
  309. ret->p = state->p; /* structure copy */
  310. ret->sflags = snewn(w*h, unsigned int);
  311. copy_game_flags(state, ret);
  312. ret->numbers = state->numbers;
  313. state->numbers->refcount++;
  314. ret->num_errors = snewn(w+h, int);
  315. memcpy(ret->num_errors, state->num_errors, (w+h)*sizeof(int));
  316. ret->completed = state->completed;
  317. ret->used_solve = state->used_solve;
  318. ret->impossible = state->impossible;
  319. return ret;
  320. }
  321. static void free_game(game_state *state)
  322. {
  323. if (--state->numbers->refcount <= 0) {
  324. sfree(state->numbers->numbers);
  325. sfree(state->numbers);
  326. }
  327. sfree(state->num_errors);
  328. sfree(state->sflags);
  329. sfree(state);
  330. }
  331. #define NDIRS 4
  332. static const unsigned int dirs_const[] = { U, D, L, R };
  333. static unsigned int find_direction(game_state *state, random_state *rs,
  334. int x, int y)
  335. {
  336. int i, nx, ny, w=state->p.w, h=state->p.h;
  337. unsigned int dirs[NDIRS];
  338. memcpy(dirs, dirs_const, sizeof(dirs));
  339. shuffle(dirs, NDIRS, sizeof(*dirs), rs);
  340. for (i = 0; i < NDIRS; i++) {
  341. nx = x + DX(dirs[i]);
  342. ny = y + DY(dirs[i]);
  343. if (nx >= 0 && nx < w && ny == h) {
  344. /* off the bottom of the board: we've finished the path. */
  345. return dirs[i];
  346. } else if (!INGRID(state, nx, ny)) {
  347. /* off the board: can't move here */
  348. continue;
  349. } else if (S_E_COUNT(state, nx, ny, E_TRACK) > 0) {
  350. /* already tracks here: can't move */
  351. continue;
  352. }
  353. return dirs[i];
  354. }
  355. return 0; /* no possible directions left. */
  356. }
  357. static bool check_completion(game_state *state, bool mark);
  358. static void lay_path(game_state *state, random_state *rs)
  359. {
  360. int px, py, w=state->p.w, h=state->p.h;
  361. unsigned int d;
  362. start:
  363. clear_game(state);
  364. /* pick a random entry point, lay its left edge */
  365. state->numbers->row_s = py = random_upto(rs, h);
  366. px = 0;
  367. S_E_SET(state, px, py, L, E_TRACK);
  368. while (INGRID(state, px, py)) {
  369. d = find_direction(state, rs, px, py);
  370. if (d == 0)
  371. goto start; /* nowhere else to go, restart */
  372. S_E_SET(state, px, py, d, E_TRACK);
  373. px += DX(d);
  374. py += DY(d);
  375. }
  376. /* double-check we got to the right place */
  377. assert(px >= 0 && px < w && py == h);
  378. state->numbers->col_s = px;
  379. }
  380. static int tracks_solve(game_state *state, int diff, int *max_diff_out);
  381. static void debug_state(game_state *state, const char *what);
  382. /* Clue-setting algorithm:
  383. - first lay clues randomly until it's soluble
  384. - then remove clues randomly if removing them doesn't affect solubility
  385. - We start with two clues, one at each path entrance.
  386. More details:
  387. - start with an array of all square i positions
  388. - if the grid is already soluble by a level easier than we've requested,
  389. go back and make a new grid
  390. - if the grid is already soluble by our requested difficulty level, skip
  391. the clue-laying step
  392. - count the number of flags the solver managed to place, remember this.
  393. - to lay clues:
  394. - shuffle the i positions
  395. - for each possible clue position:
  396. - copy the solved board, strip it
  397. - take the next position, add a clue there on the copy
  398. - try and solve the copy
  399. - if it's soluble by a level easier than we've requested, continue (on
  400. to next clue position: putting a clue here makes it too easy)
  401. - if it's soluble by our difficulty level, we're done:
  402. - put the clue flag into the solved board
  403. - go to strip-clues.
  404. - if the solver didn't manage to place any more flags, continue (on to next
  405. clue position: putting a clue here didn't help he solver)
  406. - otherwise put the clue flag in the original board, and go on to the next
  407. clue position
  408. - if we get here and we've not solved it yet, we never will (did we really
  409. fill _all_ the clues in?!). Go back and make a new grid.
  410. - to strip clues:
  411. - shuffle the i positions
  412. - for each possible clue position:
  413. - if the solved grid doesn't have a clue here, skip
  414. - copy the solved board, remove this clue, strip it
  415. - try and solve the copy
  416. - assert that it is not soluble by a level easier than we've requested
  417. - (because this should never happen)
  418. - if this is (still) soluble by our difficulty level:
  419. - remove this clue from the solved board, it's redundant (with the other
  420. clues)
  421. - that should be it.
  422. */
  423. static game_state *copy_and_strip(const game_state *state, game_state *ret, int flipcluei)
  424. {
  425. int i, j, w = state->p.w, h = state->p.h;
  426. copy_game_flags(state, ret);
  427. /* Add/remove a clue before stripping, if required */
  428. if (flipcluei != -1)
  429. ret->sflags[flipcluei] ^= S_CLUE;
  430. /* All squares that are not clue squares have square track info erased, and some edge flags.. */
  431. for (i = 0; i < w*h; i++) {
  432. if (!(ret->sflags[i] & S_CLUE)) {
  433. ret->sflags[i] &= ~(S_TRACK|S_NOTRACK|S_ERROR|S_MARK);
  434. for (j = 0; j < 4; j++) {
  435. unsigned f = 1<<j;
  436. int xx = i%w + DX(f), yy = i/w + DY(f);
  437. if (!INGRID(state, xx, yy) || !(ret->sflags[yy*w+xx] & S_CLUE)) {
  438. /* only erase an edge flag if neither side of the edge is S_CLUE. */
  439. S_E_CLEAR(ret, i%w, i/w, f, E_TRACK);
  440. S_E_CLEAR(ret, i%w, i/w, f, E_NOTRACK);
  441. }
  442. }
  443. }
  444. }
  445. return ret;
  446. }
  447. #ifdef STANDALONE_SOLVER
  448. #include <stdarg.h>
  449. static FILE *solver_diagnostics_fp = NULL;
  450. static void solver_diagnostic(const char *fmt, ...)
  451. {
  452. va_list ap;
  453. va_start(ap, fmt);
  454. vfprintf(solver_diagnostics_fp, fmt, ap);
  455. va_end(ap);
  456. fputc('\n', solver_diagnostics_fp);
  457. }
  458. #define solverdebug(printf_params) do { \
  459. if (solver_diagnostics_fp) { \
  460. solver_diagnostic printf_params; \
  461. } \
  462. } while (0)
  463. #else
  464. #define solverdebug(printf_params) ((void)0)
  465. #endif
  466. static int solve_progress(const game_state *state) {
  467. int i, w = state->p.w, h = state->p.h, progress = 0;
  468. /* Work out how many flags the solver managed to set (either TRACK
  469. or NOTRACK) and return this as a progress measure, to check whether
  470. a partially-solved board gets any further than a previous partially-
  471. solved board. */
  472. for (i = 0; i < w*h; i++) {
  473. if (state->sflags[i] & S_TRACK) progress++;
  474. if (state->sflags[i] & S_NOTRACK) progress++;
  475. progress += S_E_COUNT(state, i%w, i/w, E_TRACK);
  476. progress += S_E_COUNT(state, i%w, i/w, E_NOTRACK);
  477. }
  478. return progress;
  479. }
  480. static bool check_phantom_moves(const game_state *state) {
  481. int x, y, i;
  482. /* Check that this state won't show 'phantom moves' at the start of the
  483. * game: squares which have multiple edge flags set but no clue flag
  484. * cause a piece of track to appear that isn't on a clue square. */
  485. for (x = 0; x < state->p.w; x++) {
  486. for (y = 0; y < state->p.h; y++) {
  487. i = y*state->p.w+x;
  488. if (state->sflags[i] & S_CLUE)
  489. continue;
  490. if (S_E_COUNT(state, x, y, E_TRACK) > 1)
  491. return true; /* found one! */
  492. }
  493. }
  494. return false;
  495. }
  496. static int add_clues(game_state *state, random_state *rs, int diff)
  497. {
  498. int i, j, pi, w = state->p.w, h = state->p.h, progress, ret = 0, sr;
  499. int *positions = snewn(w*h, int), npositions = 0;
  500. int *nedges_previous_solve = snewn(w*h, int);
  501. game_state *scratch = dup_game(state);
  502. int diff_used;
  503. debug_state(state, "gen: Initial board");
  504. debug(("gen: Adding clues..."));
  505. /* set up the shuffly-position grid for later, used for adding clues:
  506. * we only bother adding clues where any edges are set. */
  507. for (i = 0; i < w*h; i++) {
  508. if (S_E_DIRS(state, i%w, i/w, E_TRACK) != 0) {
  509. positions[npositions++] = i;
  510. }
  511. nedges_previous_solve[i] = 0;
  512. }
  513. /* First, check whether the puzzle is already either too easy, or just right */
  514. scratch = copy_and_strip(state, scratch, -1);
  515. sr = tracks_solve(scratch, diff, &diff_used);
  516. if (diff_used < diff) {
  517. ret = -1; /* already too easy, even without adding clues. */
  518. debug(("gen: ...already too easy, need new board."));
  519. goto done;
  520. }
  521. if (sr < 0)
  522. assert(!"Generator should not have created impossible puzzle");
  523. if (sr > 0) {
  524. ret = 1; /* already soluble without any extra clues. */
  525. debug(("gen: ...soluble without clues, nothing to do."));
  526. goto done;
  527. }
  528. debug_state(scratch, "gen: Initial part-solved state: ");
  529. progress = solve_progress(scratch);
  530. debug(("gen: Initial solve progress is %d", progress));
  531. /* First, lay clues until we're soluble. */
  532. shuffle(positions, npositions, sizeof(int), rs);
  533. for (pi = 0; pi < npositions; pi++) {
  534. i = positions[pi]; /* pick a random position */
  535. if (state->sflags[i] & S_CLUE)
  536. continue; /* already a clue here (entrance location?) */
  537. if (nedges_previous_solve[i] == 2)
  538. continue; /* no point putting a clue here, we could solve both edges
  539. with the previous set of clues */
  540. /* set a clue in that position (on a copy of the board) and test solubility */
  541. scratch = copy_and_strip(state, scratch, i);
  542. if (check_phantom_moves(scratch))
  543. continue; /* adding a clue here would add phantom track */
  544. if (tracks_solve(scratch, diff, &diff_used) > 0) {
  545. if (diff_used < diff) {
  546. continue; /* adding a clue here makes it too easy */
  547. }
  548. /* we're now soluble (and we weren't before): add this clue, and then
  549. start stripping clues */
  550. debug(("gen: ...adding clue at (%d,%d), now soluble", i%w, i/w));
  551. state->sflags[i] |= S_CLUE;
  552. goto strip_clues;
  553. }
  554. if (solve_progress(scratch) > progress) {
  555. /* We've made more progress solving: add this clue, then. */
  556. progress = solve_progress(scratch);
  557. debug(("gen: ... adding clue at (%d,%d), new progress %d", i%w, i/w, progress));
  558. state->sflags[i] |= S_CLUE;
  559. for (j = 0; j < w*h; j++)
  560. nedges_previous_solve[j] = S_E_COUNT(scratch, j%w, j/w, E_TRACK);
  561. }
  562. }
  563. /* If we got here we didn't ever manage to make the puzzle soluble
  564. (without making it too easily soluble, that is): give up. */
  565. debug(("gen: Unable to make soluble with clues, need new board."));
  566. ret = -1;
  567. goto done;
  568. strip_clues:
  569. debug(("gen: Stripping clues."));
  570. /* Now, strip redundant clues (i.e. those without which the puzzle is still
  571. soluble) */
  572. shuffle(positions, npositions, sizeof(int), rs);
  573. for (pi = 0; pi < npositions; pi++) {
  574. i = positions[pi]; /* pick a random position */
  575. if (!(state->sflags[i] & S_CLUE))
  576. continue; /* no clue here to strip */
  577. if ((i%w == 0 && i/w == state->numbers->row_s) ||
  578. (i/w == (h-1) && i%w == state->numbers->col_s))
  579. continue; /* don't strip clues at entrance/exit */
  580. scratch = copy_and_strip(state, scratch, i);
  581. if (check_phantom_moves(scratch))
  582. continue; /* removing a clue here would add phantom track */
  583. if (tracks_solve(scratch, diff, NULL) > 0) {
  584. debug(("gen: ... removing clue at (%d,%d), still soluble without it", i%w, i/w));
  585. state->sflags[i] &= ~S_CLUE; /* still soluble without this clue. */
  586. }
  587. }
  588. debug(("gen: Finished stripping clues."));
  589. ret = 1;
  590. done:
  591. sfree(positions);
  592. sfree(nedges_previous_solve);
  593. free_game(scratch);
  594. return ret;
  595. }
  596. static char *new_game_desc(const game_params *params, random_state *rs,
  597. char **aux, bool interactive)
  598. {
  599. int i, j, w = params->w, h = params->h, x, y, ret;
  600. game_state *state;
  601. char *desc, *p;
  602. game_params adjusted_params;
  603. /*
  604. * 4x4 Tricky cannot be generated, so fall back to Easy.
  605. */
  606. if (w == 4 && h == 4 && params->diff > DIFF_EASY) {
  607. adjusted_params = *params; /* structure copy */
  608. adjusted_params.diff = DIFF_EASY;
  609. params = &adjusted_params;
  610. }
  611. state = blank_game(params);
  612. /* --- lay the random path */
  613. newpath:
  614. lay_path(state, rs);
  615. for (x = 0; x < w; x++) {
  616. for (y = 0; y < h; y++) {
  617. if (S_E_COUNT(state, x, y, E_TRACK) > 0) {
  618. state->sflags[y*w + x] |= S_TRACK;
  619. }
  620. if ((x == 0 && y == state->numbers->row_s) ||
  621. (y == (h-1) && x == state->numbers->col_s)) {
  622. state->sflags[y*w + x] |= S_CLUE;
  623. }
  624. }
  625. }
  626. /* --- Update the clue numbers based on the tracks we have generated. */
  627. for (x = 0; x < w; x++) {
  628. for (y = 0; y < h; y++) {
  629. if (state->sflags[y*w + x] & S_TRACK) {
  630. state->numbers->numbers[x]++;
  631. state->numbers->numbers[y+w]++;
  632. }
  633. }
  634. }
  635. for (i = 0; i < w+h; i++) {
  636. if (state->numbers->numbers[i] == 0)
  637. goto newpath; /* too boring */
  638. }
  639. if (params->single_ones) {
  640. bool last_was_one = true, is_one; /* disallow 1 clue at entry point */
  641. for (i = 0; i < w+h; i++) {
  642. is_one = (state->numbers->numbers[i] == 1);
  643. if (is_one && last_was_one)
  644. goto newpath; /* disallow consecutive 1 clues. */
  645. last_was_one = is_one;
  646. }
  647. if (state->numbers->numbers[w+h-1] == 1)
  648. goto newpath; /* (disallow 1 clue at exit point) */
  649. }
  650. /* --- Add clues to make a soluble puzzle */
  651. ret = add_clues(state, rs, params->diff);
  652. if (ret != 1) goto newpath; /* couldn't make it soluble, or too easy */
  653. /* --- Generate the game desc based on the generated grid. */
  654. desc = snewn(w*h*3 + (w+h)*5, char);
  655. for (i = j = 0; i < w*h; i++) {
  656. if (!(state->sflags[i] & S_CLUE) && j > 0 &&
  657. desc[j-1] >= 'a' && desc[j-1] < 'z')
  658. desc[j-1]++;
  659. else if (!(state->sflags[i] & S_CLUE))
  660. desc[j++] = 'a';
  661. else {
  662. unsigned int f = S_E_DIRS(state, i%w, i/w, E_TRACK);
  663. desc[j++] = (f < 10) ? ('0' + f) : ('A' + (f-10));
  664. }
  665. }
  666. p = desc + j;
  667. for (x = 0; x < w; x++) {
  668. p += sprintf(p, ",%s%d", x == state->numbers->col_s ? "S" : "",
  669. state->numbers->numbers[x]);
  670. }
  671. for (y = 0; y < h; y++) {
  672. p += sprintf(p, ",%s%d", y == state->numbers->row_s ? "S" : "",
  673. state->numbers->numbers[y+w]);
  674. }
  675. *p++ = '\0';
  676. ret = tracks_solve(state, DIFFCOUNT, NULL);
  677. assert(ret >= 0);
  678. free_game(state);
  679. debug(("new_game_desc: %s", desc));
  680. return desc;
  681. }
  682. static const char *validate_desc(const game_params *params, const char *desc)
  683. {
  684. int i = 0, w = params->w, h = params->h, in = 0, out = 0;
  685. while (*desc) {
  686. unsigned int f = 0;
  687. if (*desc >= '0' && *desc <= '9')
  688. f = (*desc - '0');
  689. else if (*desc >= 'A' && *desc <= 'F')
  690. f = (*desc - 'A' + 10);
  691. else if (*desc >= 'a' && *desc <= 'z')
  692. i += *desc - 'a';
  693. else
  694. return "Game description contained unexpected characters";
  695. if (f != 0) {
  696. if (nbits[f] != 2)
  697. return "Clue did not provide 2 direction flags";
  698. }
  699. i++;
  700. desc++;
  701. if (i == w*h) break;
  702. }
  703. for (i = 0; i < w+h; i++) {
  704. if (!*desc)
  705. return "Not enough numbers given after grid specification";
  706. else if (*desc != ',')
  707. return "Invalid character in number list";
  708. desc++;
  709. if (*desc == 'S') {
  710. if (i < w)
  711. out++;
  712. else
  713. in++;
  714. desc++;
  715. }
  716. while (*desc && isdigit((unsigned char)*desc)) desc++;
  717. }
  718. if (in != 1 || out != 1)
  719. return "Puzzle must have one entrance and one exit";
  720. if (*desc)
  721. return "Unexpected additional character at end of game description";
  722. return NULL;
  723. }
  724. static game_state *new_game(midend *me, const game_params *params, const char *desc)
  725. {
  726. game_state *state = blank_game(params);
  727. int w = params->w, h = params->h, i = 0;
  728. while (*desc) {
  729. unsigned int f = 0;
  730. if (*desc >= '0' && *desc <= '9')
  731. f = (*desc - '0');
  732. else if (*desc >= 'A' && *desc <= 'F')
  733. f = (*desc - 'A' + 10);
  734. else if (*desc >= 'a' && *desc <= 'z')
  735. i += *desc - 'a';
  736. if (f != 0) {
  737. int x = i % w, y = i / w;
  738. assert(f < 16);
  739. assert(nbits[f] == 2);
  740. state->sflags[i] |= (S_TRACK | S_CLUE);
  741. if (f & U) S_E_SET(state, x, y, U, E_TRACK);
  742. if (f & D) S_E_SET(state, x, y, D, E_TRACK);
  743. if (f & L) S_E_SET(state, x, y, L, E_TRACK);
  744. if (f & R) S_E_SET(state, x, y, R, E_TRACK);
  745. }
  746. i++;
  747. desc++;
  748. if (i == w*h) break;
  749. }
  750. for (i = 0; i < w+h; i++) {
  751. assert(*desc == ',');
  752. desc++;
  753. if (*desc == 'S') {
  754. if (i < w)
  755. state->numbers->col_s = i;
  756. else
  757. state->numbers->row_s = i-w;
  758. desc++;
  759. }
  760. state->numbers->numbers[i] = atoi(desc);
  761. while (*desc && isdigit((unsigned char)*desc)) desc++;
  762. }
  763. assert(!*desc);
  764. return state;
  765. }
  766. struct solver_scratch {
  767. DSF *dsf;
  768. };
  769. static int solve_set_sflag(game_state *state, int x, int y,
  770. unsigned int f, const char *why)
  771. {
  772. int w = state->p.w, i = y*w + x;
  773. if (state->sflags[i] & f)
  774. return 0;
  775. solverdebug(("square (%d,%d) -> %s: %s",
  776. x, y, (f == S_TRACK ? "TRACK" : "NOTRACK"), why));
  777. if (state->sflags[i] & (f == S_TRACK ? S_NOTRACK : S_TRACK)) {
  778. solverdebug(("opposite flag already set there, marking IMPOSSIBLE"));
  779. state->impossible = true;
  780. } else
  781. state->sflags[i] |= f;
  782. return 1;
  783. }
  784. static int solve_set_eflag(game_state *state, int x, int y, int d,
  785. unsigned int f, const char *why)
  786. {
  787. int sf = S_E_FLAGS(state, x, y, d);
  788. if (sf & f)
  789. return 0;
  790. solverdebug(("edge (%d,%d)/%c -> %s: %s", x, y,
  791. (d == U) ? 'U' : (d == D) ? 'D' : (d == L) ? 'L' : 'R',
  792. (f == S_TRACK ? "TRACK" : "NOTRACK"), why));
  793. if (sf & (f == E_TRACK ? E_NOTRACK : E_TRACK)) {
  794. solverdebug(("opposite flag already set there, marking IMPOSSIBLE"));
  795. state->impossible = true;
  796. } else
  797. S_E_SET(state, x, y, d, f);
  798. return 1;
  799. }
  800. static int solve_update_flags(game_state *state)
  801. {
  802. int x, y, i, w = state->p.w, h = state->p.h, did = 0;
  803. for (x = 0; x < w; x++) {
  804. for (y = 0; y < h; y++) {
  805. /* If a square is NOTRACK, all four edges must be. */
  806. if (state->sflags[y*w + x] & S_NOTRACK) {
  807. for (i = 0; i < 4; i++) {
  808. unsigned int d = 1<<i;
  809. did += solve_set_eflag(state, x, y, d, E_NOTRACK, "edges around NOTRACK");
  810. }
  811. }
  812. /* If 3 or more edges around a square are NOTRACK, the square is. */
  813. if (S_E_COUNT(state, x, y, E_NOTRACK) >= 3) {
  814. did += solve_set_sflag(state, x, y, S_NOTRACK, "square has >2 NOTRACK edges");
  815. }
  816. /* If any edge around a square is TRACK, the square is. */
  817. if (S_E_COUNT(state, x, y, E_TRACK) > 0) {
  818. did += solve_set_sflag(state, x, y, S_TRACK, "square has TRACK edge");
  819. }
  820. /* If a square is TRACK and 2 edges are NOTRACK,
  821. the other two edges must be TRACK. */
  822. if ((state->sflags[y*w + x] & S_TRACK) &&
  823. (S_E_COUNT(state, x, y, E_NOTRACK) == 2) &&
  824. (S_E_COUNT(state, x, y, E_TRACK) < 2)) {
  825. for (i = 0; i < 4; i++) {
  826. unsigned int d = 1<<i;
  827. if (!(S_E_FLAGS(state, x, y, d) & (E_TRACK|E_NOTRACK))) {
  828. did += solve_set_eflag(state, x, y, d, E_TRACK,
  829. "TRACK square/2 NOTRACK edges");
  830. }
  831. }
  832. }
  833. /* If a square is TRACK and 2 edges are TRACK, the other two
  834. must be NOTRACK. */
  835. if ((state->sflags[y*w + x] & S_TRACK) &&
  836. (S_E_COUNT(state, x, y, E_TRACK) == 2) &&
  837. (S_E_COUNT(state, x, y, E_NOTRACK) < 2)) {
  838. for (i = 0; i < 4; i++) {
  839. unsigned int d = 1<<i;
  840. if (!(S_E_FLAGS(state, x, y, d) & (E_TRACK|E_NOTRACK))) {
  841. did += solve_set_eflag(state, x, y, d, E_NOTRACK,
  842. "TRACK square/2 TRACK edges");
  843. }
  844. }
  845. }
  846. }
  847. }
  848. return did;
  849. }
  850. static int solve_count_col(game_state *state, int col, unsigned int f)
  851. {
  852. int i, n, c = 0, h = state->p.h, w = state->p.w;
  853. for (n = 0, i = col; n < h; n++, i += w) {
  854. if (state->sflags[i] & f) c++;
  855. }
  856. return c;
  857. }
  858. static int solve_count_row(game_state *state, int row, unsigned int f)
  859. {
  860. int i, n, c = 0, w = state->p.w;
  861. for (n = 0, i = w*row; n < state->p.w; n++, i++) {
  862. if (state->sflags[i] & f) c++;
  863. }
  864. return c;
  865. }
  866. static int solve_count_clues_sub(game_state *state, int si, int id, int n,
  867. int target, const char *what)
  868. {
  869. int ctrack = 0, cnotrack = 0, did = 0, j, i, w = state->p.w;
  870. for (j = 0, i = si; j < n; j++, i += id) {
  871. if (state->sflags[i] & S_TRACK)
  872. ctrack++;
  873. if (state->sflags[i] & S_NOTRACK)
  874. cnotrack++;
  875. }
  876. if (ctrack == target) {
  877. /* everything that's not S_TRACK must be S_NOTRACK. */
  878. for (j = 0, i = si; j < n; j++, i += id) {
  879. if (!(state->sflags[i] & S_TRACK))
  880. did += solve_set_sflag(state, i%w, i/w, S_NOTRACK, what);
  881. }
  882. }
  883. if (cnotrack == (n-target)) {
  884. /* everything that's not S_NOTRACK must be S_TRACK. */
  885. for (j = 0, i = si; j < n; j++, i += id) {
  886. if (!(state->sflags[i] & S_NOTRACK))
  887. did += solve_set_sflag(state, i%w, i/w, S_TRACK, what);
  888. }
  889. }
  890. return did;
  891. }
  892. static int solve_count_clues(game_state *state)
  893. {
  894. int w = state->p.w, h = state->p.h, x, y, target, did = 0;
  895. for (x = 0; x < w; x++) {
  896. target = state->numbers->numbers[x];
  897. did += solve_count_clues_sub(state, x, w, h, target, "col count");
  898. }
  899. for (y = 0; y < h; y++) {
  900. target = state->numbers->numbers[w+y];
  901. did += solve_count_clues_sub(state, y*w, 1, w, target, "row count");
  902. }
  903. return did;
  904. }
  905. static int solve_check_single_sub(game_state *state, int si, int id, int n,
  906. int target, unsigned int perpf,
  907. const char *what)
  908. {
  909. int ctrack = 0, nperp = 0, did = 0, j, i, w = state->p.w;
  910. int n1edge = 0, i1edge = 0, ox, oy, x, y;
  911. unsigned int impossible = 0;
  912. /* For rows or columns which only have one more square to put a track in, we
  913. know the only way a new track section could be there would be to run
  914. perpendicular to the track (otherwise we'd need at least two free squares).
  915. So, if there is nowhere we can run perpendicular to the track (e.g. because
  916. we're on an edge) we know the extra track section much be on one end of an
  917. existing section. */
  918. for (j = 0, i = si; j < n; j++, i += id) {
  919. if (state->sflags[i] & S_TRACK)
  920. ctrack++;
  921. impossible = S_E_DIRS(state, i%w, i/w, E_NOTRACK);
  922. if ((perpf & impossible) == 0)
  923. nperp++;
  924. if (S_E_COUNT(state, i%w, i/w, E_TRACK) <= 1) {
  925. n1edge++;
  926. i1edge = i;
  927. }
  928. }
  929. if (ctrack != (target-1)) return 0;
  930. if (nperp > 0 || n1edge != 1) return 0;
  931. solverdebug(("check_single from (%d,%d): 1 match from (%d,%d)",
  932. si%w, si/w, i1edge%w, i1edge/w));
  933. /* We have a match: anything that's more than 1 away from this square
  934. cannot now contain a track. */
  935. ox = i1edge%w;
  936. oy = i1edge/w;
  937. for (j = 0, i = si; j < n; j++, i += id) {
  938. x = i%w;
  939. y = i/w;
  940. if (abs(ox-x) > 1 || abs(oy-y) > 1) {
  941. if (!(state->sflags[i] & S_TRACK))
  942. did += solve_set_sflag(state, x, y, S_NOTRACK, what);
  943. }
  944. }
  945. return did;
  946. }
  947. static int solve_check_single(game_state *state)
  948. {
  949. int w = state->p.w, h = state->p.h, x, y, target, did = 0;
  950. for (x = 0; x < w; x++) {
  951. target = state->numbers->numbers[x];
  952. did += solve_check_single_sub(state, x, w, h, target, R|L, "single on col");
  953. }
  954. for (y = 0; y < h; y++) {
  955. target = state->numbers->numbers[w+y];
  956. did += solve_check_single_sub(state, y*w, 1, w, target, U|D, "single on row");
  957. }
  958. return did;
  959. }
  960. static int solve_check_loose_sub(game_state *state, int si, int id, int n,
  961. int target, unsigned int perpf,
  962. const char *what)
  963. {
  964. int nperp = 0, nloose = 0, e2count = 0, did = 0, i, j, k;
  965. int w = state->p.w;
  966. unsigned int parf = ALLDIR & (~perpf);
  967. for (j = 0, i = si; j < n; j++, i += id) {
  968. int fcount = S_E_COUNT(state, i%w, i/w, E_TRACK);
  969. if (fcount == 2)
  970. e2count++; /* this cell has 2 definite edges */
  971. state->sflags[i] &= ~S_MARK;
  972. if (fcount == 1 && (parf & S_E_DIRS(state, i%w, i/w, E_TRACK))) {
  973. nloose++; /* this cell has a loose end (single flag set parallel
  974. to the direction of this row/column) */
  975. state->sflags[i] |= S_MARK; /* mark loose ends */
  976. }
  977. if (fcount != 2 && !(perpf & S_E_DIRS(state, i%w, i/w, E_NOTRACK)))
  978. nperp++; /* we could lay perpendicular across this cell */
  979. }
  980. if (nloose > (target - e2count)) {
  981. solverdebug(("check %s from (%d,%d): more loose (%d) than empty (%d), IMPOSSIBLE",
  982. what, si%w, si/w, nloose, target-e2count));
  983. state->impossible = true;
  984. }
  985. if (nloose > 0 && nloose == (target - e2count)) {
  986. solverdebug(("check %s from (%d,%d): nloose = empty (%d), forcing loners out.",
  987. what, si%w, si/w, nloose));
  988. for (j = 0, i = si; j < n; j++, i += id) {
  989. if (!(state->sflags[i] & S_MARK))
  990. continue; /* skip non-loose ends */
  991. if (j > 0 && state->sflags[i-id] & S_MARK)
  992. continue; /* next to other loose end, could join up */
  993. if (j < (n-1) && state->sflags[i+id] & S_MARK)
  994. continue; /* ditto */
  995. for (k = 0; k < 4; k++) {
  996. if ((parf & (1<<k)) &&
  997. !(S_E_DIRS(state, i%w, i/w, E_TRACK) & (1<<k))) {
  998. /* set as NOTRACK the edge parallel to the row/column that's
  999. not already set. */
  1000. did += solve_set_eflag(state, i%w, i/w, 1<<k, E_NOTRACK, what);
  1001. }
  1002. }
  1003. }
  1004. }
  1005. if (nloose == 1 && (target - e2count) == 2 && nperp == 0) {
  1006. solverdebug(("check %s from (%d,%d): 1 loose end, 2 empty squares, forcing parallel",
  1007. what, si%w, si/w));
  1008. for (j = 0, i = si; j < n; j++, i += id) {
  1009. if (!(state->sflags[i] & S_MARK))
  1010. continue; /* skip non-loose ends */
  1011. for (k = 0; k < 4; k++) {
  1012. if (parf & (1<<k))
  1013. did += solve_set_eflag(state, i%w, i/w, 1<<k, E_TRACK, what);
  1014. }
  1015. }
  1016. }
  1017. return did;
  1018. }
  1019. static int solve_check_loose_ends(game_state *state)
  1020. {
  1021. int w = state->p.w, h = state->p.h, x, y, target, did = 0;
  1022. for (x = 0; x < w; x++) {
  1023. target = state->numbers->numbers[x];
  1024. did += solve_check_loose_sub(state, x, w, h, target, R|L, "loose on col");
  1025. }
  1026. for (y = 0; y < h; y++) {
  1027. target = state->numbers->numbers[w+y];
  1028. did += solve_check_loose_sub(state, y*w, 1, w, target, U|D, "loose on row");
  1029. }
  1030. return did;
  1031. }
  1032. static void solve_check_neighbours_count(
  1033. game_state *state, int start, int step, int n, int clueindex,
  1034. bool *onefill, bool *oneempty)
  1035. {
  1036. int to_fill = state->numbers->numbers[clueindex];
  1037. int to_empty = n - to_fill;
  1038. int i;
  1039. for (i = 0; i < n; i++) {
  1040. int p = start + i*step;
  1041. if (state->sflags[p] & S_TRACK)
  1042. to_fill--;
  1043. if (state->sflags[p] & S_NOTRACK)
  1044. to_empty--;
  1045. }
  1046. *onefill = (to_fill == 1);
  1047. *oneempty = (to_empty == 1);
  1048. }
  1049. static int solve_check_neighbours_try(game_state *state, int x, int y,
  1050. int X, int Y, bool onefill,
  1051. bool oneempty, unsigned dir,
  1052. const char *what)
  1053. {
  1054. int w = state->p.w, p = y*w+x, P = Y*w+X;
  1055. /*
  1056. * We're given a neighbouring pair of squares p,P, with 'dir'
  1057. * being the direction from the former to the latter. We aim to
  1058. * spot situations in which, if p is a track square, then P must
  1059. * also be one (because p doesn't have enough free exits to avoid
  1060. * using the one that goes towards P).
  1061. *
  1062. * Then, if the target number of track squares on their shared
  1063. * row/column says that there's only one track square left to
  1064. * place, it can't be p, because P would have to be one too,
  1065. * violating the clue. So in that situation we can mark p as
  1066. * unfilled. Conversely, if there's only one _non_-track square
  1067. * left to place, it can't be P, so we can mark P as filled.
  1068. */
  1069. if ((state->sflags[p] | state->sflags[P]) & (S_TRACK | S_NOTRACK))
  1070. return 0; /* no need: we already know something about these squares */
  1071. int possible_exits_except_dir = nbits[
  1072. ALLDIR & ~dir & ~S_E_DIRS(state, x, y, E_NOTRACK)];
  1073. if (possible_exits_except_dir >= 2)
  1074. return 0; /* square p need not connect to P, even if it is filled */
  1075. /* OK, now we know that if p is filled, P must be filled too. */
  1076. int did = 0;
  1077. if (onefill) {
  1078. /* But at most one of them can be filled, so it can't be p. */
  1079. state->sflags[p] |= S_NOTRACK;
  1080. solverdebug(("square (%d,%d) -> NOTRACK: otherwise, that and (%d,%d) "
  1081. "would make too many TRACK in %s", x, y, X, Y, what));
  1082. did++;
  1083. }
  1084. if (oneempty) {
  1085. /* Alternatively, at least one of them _must_ be filled, so P
  1086. * must be. */
  1087. state->sflags[P] |= S_TRACK;
  1088. solverdebug(("square (%d,%d) -> TRACK: otherwise, that and (%d,%d) "
  1089. "would make too many NOTRACK in %s", X, Y, x, y, what));
  1090. did++;
  1091. }
  1092. return did;
  1093. }
  1094. static int solve_check_neighbours(game_state *state, bool both_ways)
  1095. {
  1096. int w = state->p.w, h = state->p.h, x, y, did = 0;
  1097. bool onefill, oneempty;
  1098. for (x = 0; x < w; x++) {
  1099. solve_check_neighbours_count(state, x, w, h, x, &onefill, &oneempty);
  1100. if (!both_ways)
  1101. oneempty = false; /* disable the harder version of the deduction */
  1102. if (!onefill && !oneempty)
  1103. continue;
  1104. for (y = 0; y+1 < h; y++) {
  1105. did += solve_check_neighbours_try(state, x, y, x, y+1,
  1106. onefill, oneempty, D, "column");
  1107. did += solve_check_neighbours_try(state, x, y+1, x, y,
  1108. onefill, oneempty, U, "column");
  1109. }
  1110. }
  1111. for (y = 0; y < h; y++) {
  1112. solve_check_neighbours_count(state, y*w, 1, w, w+y,
  1113. &onefill, &oneempty);
  1114. if (!both_ways)
  1115. oneempty = false; /* disable the harder version of the deduction */
  1116. if (!onefill && !oneempty)
  1117. continue;
  1118. for (x = 0; x+1 < w; x++) {
  1119. did += solve_check_neighbours_try(state, x, y, x+1, y,
  1120. onefill, oneempty, R, "row");
  1121. did += solve_check_neighbours_try(state, x+1, y, x, y,
  1122. onefill, oneempty, L, "row");
  1123. }
  1124. }
  1125. return did;
  1126. }
  1127. static int solve_check_loop_sub(game_state *state, int x, int y, int dir,
  1128. DSF *dsf, int startc, int endc)
  1129. {
  1130. int w = state->p.w, h = state->p.h, i = y*w+x, j, k;
  1131. bool satisfied = true;
  1132. j = (y+DY(dir))*w + (x+DX(dir));
  1133. assert(i < w*h && j < w*h);
  1134. if ((state->sflags[i] & S_TRACK) &&
  1135. (state->sflags[j] & S_TRACK) &&
  1136. !(S_E_DIRS(state, x, y, E_TRACK) & dir) &&
  1137. !(S_E_DIRS(state, x, y, E_NOTRACK) & dir)) {
  1138. int ic = dsf_canonify(dsf, i), jc = dsf_canonify(dsf, j);
  1139. if (ic == jc) {
  1140. return solve_set_eflag(state, x, y, dir, E_NOTRACK, "would close loop");
  1141. }
  1142. if ((ic == startc && jc == endc) || (ic == endc && jc == startc)) {
  1143. solverdebug(("Adding link at (%d,%d) would join start to end", x, y));
  1144. /* We mustn't join the start to the end if:
  1145. - there are other bits of track that aren't attached to either end
  1146. - the clues are not fully satisfied yet
  1147. */
  1148. for (k = 0; k < w*h; k++) {
  1149. if (state->sflags[k] & S_TRACK &&
  1150. dsf_canonify(dsf, k) != startc && dsf_canonify(dsf, k) != endc) {
  1151. return solve_set_eflag(state, x, y, dir, E_NOTRACK,
  1152. "joins start to end but misses tracks");
  1153. }
  1154. }
  1155. for (k = 0; k < w; k++) {
  1156. int target = state->numbers->numbers[k];
  1157. int ntracks = solve_count_col(state, k, S_TRACK);
  1158. if (ntracks < target) satisfied = false;
  1159. }
  1160. for (k = 0; k < h; k++) {
  1161. int target = state->numbers->numbers[w+k];
  1162. int ntracks = solve_count_row(state, k, S_TRACK);
  1163. if (ntracks < target) satisfied = false;
  1164. }
  1165. if (!satisfied) {
  1166. return solve_set_eflag(state, x, y, dir, E_NOTRACK,
  1167. "joins start to end with incomplete clues");
  1168. }
  1169. }
  1170. }
  1171. return 0;
  1172. }
  1173. static int solve_check_loop(game_state *state)
  1174. {
  1175. int w = state->p.w, h = state->p.h, x, y, i, j, did = 0;
  1176. DSF *dsf;
  1177. int startc, endc;
  1178. /* TODO eventually we should pull this out into a solver struct and keep it
  1179. updated as we connect squares. For now we recreate it every time we try
  1180. this particular solver step. */
  1181. dsf = dsf_new(w*h);
  1182. /* Work out the connectedness of the current loop set. */
  1183. for (x = 0; x < w; x++) {
  1184. for (y = 0; y < h; y++) {
  1185. i = y*w + x;
  1186. if (x < (w-1) && S_E_DIRS(state, x, y, E_TRACK) & R) {
  1187. /* connection to the right... */
  1188. j = y*w + (x+1);
  1189. assert(i < w*h && j < w*h);
  1190. dsf_merge(dsf, i, j);
  1191. }
  1192. if (y < (h-1) && S_E_DIRS(state, x, y, E_TRACK) & D) {
  1193. /* connection down... */
  1194. j = (y+1)*w + x;
  1195. assert(i < w*h && j < w*h);
  1196. dsf_merge(dsf, i, j);
  1197. }
  1198. /* NB no need to check up and left because they'll have been checked
  1199. by the other side. */
  1200. }
  1201. }
  1202. startc = dsf_canonify(dsf, state->numbers->row_s*w);
  1203. endc = dsf_canonify(dsf, (h-1)*w+state->numbers->col_s);
  1204. /* Now look at all adjacent squares that are both S_TRACK: if connecting
  1205. any of them would complete a loop (i.e. they're both the same dsf class
  1206. already) then that edge must be NOTRACK. */
  1207. for (x = 0; x < w; x++) {
  1208. for (y = 0; y < h; y++) {
  1209. if (x < (w-1))
  1210. did += solve_check_loop_sub(state, x, y, R, dsf, startc, endc);
  1211. if (y < (h-1))
  1212. did += solve_check_loop_sub(state, x, y, D, dsf, startc, endc);
  1213. }
  1214. }
  1215. dsf_free(dsf);
  1216. return did;
  1217. }
  1218. static void solve_discount_edge(game_state *state, int x, int y, int d)
  1219. {
  1220. if (S_E_DIRS(state, x, y, E_TRACK) & d) {
  1221. assert(state->sflags[y*state->p.w + x] & S_CLUE);
  1222. return; /* (only) clue squares can have outer edges set. */
  1223. }
  1224. solve_set_eflag(state, x, y, d, E_NOTRACK, "outer edge");
  1225. }
  1226. static int solve_bridge_sub(game_state *state, int x, int y, int d,
  1227. struct solver_scratch *sc)
  1228. {
  1229. /*
  1230. * Imagine a graph on the squares of the grid, with an edge
  1231. * connecting neighbouring squares only if it's not yet known
  1232. * whether there's a track between them.
  1233. *
  1234. * This function is called if the edge between x,y and X,Y is a
  1235. * bridge in that graph: that is, it's not part of any loop in the
  1236. * graph, or equivalently, removing it would increase the number
  1237. * of connected components in the graph.
  1238. *
  1239. * In that situation, we can fill in the edge by a parity
  1240. * argument. Construct a closed loop of edges in the grid, all of
  1241. * whose states are known except this one. The track starts and
  1242. * ends outside this loop, so it must cross the boundary of the
  1243. * loop an even number of times. So if we count up how many times
  1244. * the track is known to cross the edges of our loop, then we can
  1245. * fill in the last edge in whichever way makes that number even.
  1246. *
  1247. * In fact, there's not even any need to go to the effort of
  1248. * constructing a _single_ closed loop. The simplest thing is to
  1249. * delete the bridge edge from the graph, find a connected
  1250. * component of the reduced graph whose boundary includes that
  1251. * edge, and take every edge separating that component from
  1252. * another. This may not lead to _exactly one_ cycle - the
  1253. * component could be non-simply connected and have a hole in the
  1254. * middle - but that doesn't matter, because the same parity
  1255. * constraint applies just as well with more than one disjoint
  1256. * loop.
  1257. */
  1258. int w = state->p.w, h = state->p.h, wh = w*h;
  1259. int X = x + DX(d), Y = y + DY(d);
  1260. int xi, yi, di;
  1261. assert(d == D || d == R);
  1262. if (!sc->dsf)
  1263. sc->dsf = dsf_new(wh);
  1264. dsf_reinit(sc->dsf);
  1265. for (xi = 0; xi < w; xi++) {
  1266. for (yi = 0; yi < h; yi++) {
  1267. /* We expect to have been called with X,Y either to the
  1268. * right of x,y or below it, not the other way round. If
  1269. * that were not true, the tests in this loop to exclude
  1270. * the bridge edge would have to be twice as annoying. */
  1271. if (yi+1 < h && !S_E_FLAGS(state, xi, yi, D) &&
  1272. !(xi == x && yi == y && xi == X && yi+1 == Y))
  1273. dsf_merge(sc->dsf, yi*w+xi, (yi+1)*w+xi);
  1274. if (xi+1 < w && !S_E_FLAGS(state, xi, yi, R) &&
  1275. !(xi == x && yi == y && xi+1 == X && yi == Y))
  1276. dsf_merge(sc->dsf, yi*w+xi, yi*w+(xi+1));
  1277. }
  1278. }
  1279. int component = dsf_canonify(sc->dsf, y*w+x);
  1280. int parity = 0;
  1281. for (xi = 0; xi < w; xi++) {
  1282. for (yi = 0; yi < h; yi++) {
  1283. if (dsf_canonify(sc->dsf, yi*w+xi) != component)
  1284. continue;
  1285. for (di = 1; di < 16; di *= 2) {
  1286. int Xi = xi + DX(di), Yi = yi + DY(di);
  1287. if ((Xi < 0 || Xi >= w || Yi < 0 || Yi >= h ||
  1288. dsf_canonify(sc->dsf, Yi*w+Xi) != component) &&
  1289. (S_E_DIRS(state, xi, yi, E_TRACK) & di))
  1290. parity ^= 1;
  1291. }
  1292. }
  1293. }
  1294. solve_set_eflag(state, x, y, d, parity ? E_TRACK : E_NOTRACK, "parity");
  1295. return 1;
  1296. }
  1297. struct solve_bridge_neighbour_ctx {
  1298. game_state *state;
  1299. int x, y, dirs;
  1300. };
  1301. static int solve_bridge_neighbour(int vertex, void *vctx)
  1302. {
  1303. struct solve_bridge_neighbour_ctx *ctx =
  1304. (struct solve_bridge_neighbour_ctx *)vctx;
  1305. int w = ctx->state->p.w;
  1306. if (vertex >= 0) {
  1307. ctx->x = vertex % w;
  1308. ctx->y = vertex / w;
  1309. ctx->dirs = ALLDIR
  1310. & ~S_E_DIRS(ctx->state, ctx->x, ctx->y, E_TRACK)
  1311. & ~S_E_DIRS(ctx->state, ctx->x, ctx->y, E_NOTRACK);
  1312. }
  1313. unsigned dir = ctx->dirs & -ctx->dirs; /* isolate lowest set bit */
  1314. if (!dir)
  1315. return -1;
  1316. ctx->dirs &= ~dir;
  1317. int xr = ctx->x + DX(dir), yr = ctx->y + DY(dir);
  1318. assert(0 <= xr && xr < w);
  1319. assert(0 <= yr && yr < ctx->state->p.h);
  1320. return yr * w + xr;
  1321. }
  1322. static int solve_check_bridge_parity(game_state *state,
  1323. struct solver_scratch *sc)
  1324. {
  1325. int w = state->p.w, h = state->p.h, wh = w*h;
  1326. struct findloopstate *fls;
  1327. struct solve_bridge_neighbour_ctx ctx[1];
  1328. int x, y, did = 0;
  1329. ctx->state = state;
  1330. fls = findloop_new_state(wh);
  1331. findloop_run(fls, wh, solve_bridge_neighbour, ctx);
  1332. for (x = 0; x < w; x++) {
  1333. for (y = 0; y < h; y++) {
  1334. if (y+1 < h && !findloop_is_loop_edge(fls, y*w+x, (y+1)*w+x))
  1335. did += solve_bridge_sub(state, x, y, D, sc);
  1336. if (x+1 < w && !findloop_is_loop_edge(fls, y*w+x, y*w+(x+1)))
  1337. did += solve_bridge_sub(state, x, y, R, sc);
  1338. }
  1339. }
  1340. findloop_free_state(fls);
  1341. return did;
  1342. }
  1343. static int tracks_solve(game_state *state, int diff, int *max_diff_out)
  1344. {
  1345. int x, y, w = state->p.w, h = state->p.h;
  1346. struct solver_scratch sc[1];
  1347. int max_diff = DIFF_EASY;
  1348. sc->dsf = NULL;
  1349. debug(("solve..."));
  1350. state->impossible = false;
  1351. /* Set all the outer border edges as no-track. */
  1352. for (x = 0; x < w; x++) {
  1353. solve_discount_edge(state, x, 0, U);
  1354. solve_discount_edge(state, x, h-1, D);
  1355. }
  1356. for (y = 0; y < h; y++) {
  1357. solve_discount_edge(state, 0, y, L);
  1358. solve_discount_edge(state, w-1, y, R);
  1359. }
  1360. while (!state->impossible) {
  1361. /* Can't use do ... while (0) because we need a 'continue' in this macro */
  1362. #define TRY(curr_diff, funcall) \
  1363. if (diff >= (curr_diff) && (funcall)) { \
  1364. if (max_diff < curr_diff) \
  1365. max_diff = curr_diff; \
  1366. continue; \
  1367. } else ((void)0)
  1368. TRY(DIFF_EASY, solve_update_flags(state));
  1369. TRY(DIFF_EASY, solve_count_clues(state));
  1370. TRY(DIFF_EASY, solve_check_loop(state));
  1371. TRY(DIFF_TRICKY, solve_check_single(state));
  1372. TRY(DIFF_TRICKY, solve_check_loose_ends(state));
  1373. TRY(DIFF_TRICKY, solve_check_neighbours(state, false));
  1374. TRY(DIFF_HARD, solve_check_neighbours(state, true));
  1375. TRY(DIFF_HARD, solve_check_bridge_parity(state, sc));
  1376. #undef TRY
  1377. break;
  1378. }
  1379. dsf_free(sc->dsf);
  1380. if (max_diff_out)
  1381. *max_diff_out = max_diff;
  1382. return state->impossible ? -1 : check_completion(state, false) ? 1 : 0;
  1383. }
  1384. static char *move_string_diff(const game_state *before, const game_state *after, bool issolve)
  1385. {
  1386. int w = after->p.w, h = after->p.h, i, j;
  1387. char *move = snewn(w*h*40, char), *p = move;
  1388. const char *sep = "";
  1389. unsigned int otf, ntf, onf, nnf;
  1390. if (issolve) {
  1391. *p++ = 'S';
  1392. sep = ";";
  1393. }
  1394. for (i = 0; i < w*h; i++) {
  1395. otf = S_E_DIRS(before, i%w, i/w, E_TRACK);
  1396. ntf = S_E_DIRS(after, i%w, i/w, E_TRACK);
  1397. onf = S_E_DIRS(before, i%w, i/w, E_NOTRACK);
  1398. nnf = S_E_DIRS(after, i%w, i/w, E_NOTRACK);
  1399. for (j = 0; j < 4; j++) {
  1400. unsigned df = 1<<j;
  1401. if ((otf & df) != (ntf & df)) {
  1402. p += sprintf(p, "%s%c%c%d,%d", sep,
  1403. (ntf & df) ? 'T' : 't', MOVECHAR(df), i%w, i/w);
  1404. sep = ";";
  1405. }
  1406. if ((onf & df) != (nnf & df)) {
  1407. p += sprintf(p, "%s%c%c%d,%d", sep,
  1408. (nnf & df) ? 'N' : 'n', MOVECHAR(df), i%w, i/w);
  1409. sep = ";";
  1410. }
  1411. }
  1412. if ((before->sflags[i] & S_NOTRACK) != (after->sflags[i] & S_NOTRACK)) {
  1413. p += sprintf(p, "%s%cS%d,%d", sep,
  1414. (after->sflags[i] & S_NOTRACK) ? 'N' : 'n', i%w, i/w);
  1415. sep = ";";
  1416. }
  1417. if ((before->sflags[i] & S_TRACK) != (after->sflags[i] & S_TRACK)) {
  1418. p += sprintf(p, "%s%cS%d,%d", sep,
  1419. (after->sflags[i] & S_TRACK) ? 'T' : 't', i%w, i/w);
  1420. sep = ";";
  1421. }
  1422. }
  1423. *p++ = '\0';
  1424. move = sresize(move, p - move, char);
  1425. return move;
  1426. }
  1427. static char *solve_game(const game_state *state, const game_state *currstate,
  1428. const char *aux, const char **error)
  1429. {
  1430. game_state *solved;
  1431. int ret;
  1432. char *move;
  1433. solved = dup_game(currstate);
  1434. ret = tracks_solve(solved, DIFFCOUNT, NULL);
  1435. if (ret < 1) {
  1436. free_game(solved);
  1437. solved = dup_game(state);
  1438. ret = tracks_solve(solved, DIFFCOUNT, NULL);
  1439. }
  1440. if (ret < 1) {
  1441. *error = "Unable to find solution";
  1442. move = NULL;
  1443. } else {
  1444. move = move_string_diff(currstate, solved, true);
  1445. }
  1446. free_game(solved);
  1447. return move;
  1448. }
  1449. static bool game_can_format_as_text_now(const game_params *params)
  1450. {
  1451. return true;
  1452. }
  1453. static char *game_text_format(const game_state *state)
  1454. {
  1455. char *ret, *p;
  1456. int x, y, len, w = state->p.w, h = state->p.h;
  1457. len = ((w*2) + 4) * ((h*2)+4) + 2;
  1458. ret = snewn(len+1, char);
  1459. p = ret;
  1460. /* top line: column clues */
  1461. *p++ = ' ';
  1462. *p++ = ' ';
  1463. for (x = 0; x < w; x++) {
  1464. *p++ = (state->numbers->numbers[x] < 10 ?
  1465. '0' + state->numbers->numbers[x] :
  1466. 'A' + state->numbers->numbers[x] - 10);
  1467. *p++ = ' ';
  1468. }
  1469. *p++ = '\n';
  1470. /* second line: top edge */
  1471. *p++ = ' ';
  1472. *p++ = '+';
  1473. for (x = 0; x < w*2-1; x++)
  1474. *p++ = '-';
  1475. *p++ = '+';
  1476. *p++ = '\n';
  1477. /* grid rows: one line of squares, one line of edges. */
  1478. for (y = 0; y < h; y++) {
  1479. /* grid square line */
  1480. *p++ = (y == state->numbers->row_s) ? 'A' : ' ';
  1481. *p++ = (y == state->numbers->row_s) ? '-' : '|';
  1482. for (x = 0; x < w; x++) {
  1483. unsigned int f = S_E_DIRS(state, x, y, E_TRACK);
  1484. if (state->sflags[y*w+x] & S_CLUE) *p++ = 'C';
  1485. else if (f == LU || f == RD) *p++ = '/';
  1486. else if (f == LD || f == RU) *p++ = '\\';
  1487. else if (f == UD) *p++ = '|';
  1488. else if (f == RL) *p++ = '-';
  1489. else if (state->sflags[y*w+x] & S_NOTRACK) *p++ = 'x';
  1490. else *p++ = ' ';
  1491. if (x < w-1) {
  1492. *p++ = (f & R) ? '-' : ' ';
  1493. } else
  1494. *p++ = '|';
  1495. }
  1496. *p++ = (state->numbers->numbers[w+y] < 10 ?
  1497. '0' + state->numbers->numbers[w+y] :
  1498. 'A' + state->numbers->numbers[w+y] - 10);
  1499. *p++ = '\n';
  1500. if (y == h-1) continue;
  1501. /* edges line */
  1502. *p++ = ' ';
  1503. *p++ = '|';
  1504. for (x = 0; x < w; x++) {
  1505. unsigned int f = S_E_DIRS(state, x, y, E_TRACK);
  1506. *p++ = (f & D) ? '|' : ' ';
  1507. *p++ = (x < w-1) ? ' ' : '|';
  1508. }
  1509. *p++ = '\n';
  1510. }
  1511. /* next line: bottom edge */
  1512. *p++ = ' ';
  1513. *p++ = '+';
  1514. for (x = 0; x < w*2-1; x++)
  1515. *p++ = (x == state->numbers->col_s*2) ? '|' : '-';
  1516. *p++ = '+';
  1517. *p++ = '\n';
  1518. /* final line: bottom clue */
  1519. *p++ = ' ';
  1520. *p++ = ' ';
  1521. for (x = 0; x < w*2-1; x++)
  1522. *p++ = (x == state->numbers->col_s*2) ? 'B' : ' ';
  1523. *p++ = '\n';
  1524. *p = '\0';
  1525. return ret;
  1526. }
  1527. static void debug_state(game_state *state, const char *what) {
  1528. char *sstring = game_text_format(state);
  1529. debug(("%s: %s", what, sstring));
  1530. sfree(sstring);
  1531. }
  1532. static void dsf_update_completion(game_state *state, int ax, int ay,
  1533. char dir, DSF *dsf)
  1534. {
  1535. int w = state->p.w, ai = ay*w+ax, bx, by, bi;
  1536. if (!(S_E_DIRS(state, ax, ay, E_TRACK) & dir)) return;
  1537. bx = ax + DX(dir);
  1538. by = ay + DY(dir);
  1539. if (!INGRID(state, bx, by)) return;
  1540. bi = by*w+bx;
  1541. dsf_merge(dsf, ai, bi);
  1542. }
  1543. struct tracks_neighbour_ctx {
  1544. game_state *state;
  1545. int i, n, neighbours[4];
  1546. };
  1547. static int tracks_neighbour(int vertex, void *vctx)
  1548. {
  1549. struct tracks_neighbour_ctx *ctx = (struct tracks_neighbour_ctx *)vctx;
  1550. if (vertex >= 0) {
  1551. game_state *state = ctx->state;
  1552. int w = state->p.w, x = vertex % w, y = vertex / w;
  1553. int dirs = S_E_DIRS(state, x, y, E_TRACK);
  1554. int j;
  1555. ctx->i = ctx->n = 0;
  1556. for (j = 0; j < 4; j++) {
  1557. int dir = 1<<j;
  1558. if (dirs & dir) {
  1559. int nx = x + DX(dir), ny = y + DY(dir);
  1560. if (INGRID(state, nx, ny))
  1561. ctx->neighbours[ctx->n++] = ny * w + nx;
  1562. }
  1563. }
  1564. }
  1565. if (ctx->i < ctx->n)
  1566. return ctx->neighbours[ctx->i++];
  1567. else
  1568. return -1;
  1569. }
  1570. /*
  1571. * The completion flash moves along the track, so we want to label
  1572. * each tile with how far along the track it is. This is represented
  1573. * as an eight-bit field, which is more than enough when the
  1574. * completion flash is only 0.5 s long.
  1575. */
  1576. static void set_flash_data(game_state *state)
  1577. {
  1578. int ntrack = 0, x, y, n, d;
  1579. const int w = state->p.w;
  1580. for (x = 0; x < w; x++)
  1581. ntrack += state->numbers->numbers[x];
  1582. n = 0; x = 0; y = state->numbers->row_s; d = R;
  1583. do {
  1584. state->sflags[y*w + x] &= ~(S_FLASH_MASK << S_FLASH_SHIFT);
  1585. state->sflags[y*w + x] |=
  1586. n++ * (S_FLASH_MASK / (ntrack - 1)) << S_FLASH_SHIFT;
  1587. d = F(d); /* Find the direction we just arrived from. */
  1588. d = S_E_DIRS(state, x, y, E_TRACK) & ~d; /* Other track from here. */
  1589. x += DX(d); y += DY(d); /* Move to the next tile. */
  1590. } while (INGRID(state, x, y));
  1591. }
  1592. static bool check_completion(game_state *state, bool mark)
  1593. {
  1594. int w = state->p.w, h = state->p.h, x, y, i, target;
  1595. bool ret = true, pathret;
  1596. int ntrack, nnotrack, ntrackcomplete;
  1597. DSF *dsf;
  1598. int pathclass;
  1599. struct findloopstate *fls;
  1600. struct tracks_neighbour_ctx ctx;
  1601. if (mark) {
  1602. for (i = 0; i < w+h; i++) {
  1603. state->num_errors[i] = 0;
  1604. }
  1605. for (i = 0; i < w*h; i++) {
  1606. state->sflags[i] &= ~S_ERROR;
  1607. if (S_E_COUNT(state, i%w, i/w, E_TRACK) > 0) {
  1608. if (S_E_COUNT(state, i%w, i/w, E_TRACK) > 2) {
  1609. ret = false;
  1610. state->sflags[i] |= S_ERROR;
  1611. }
  1612. }
  1613. }
  1614. }
  1615. dsf = dsf_new(w*h);
  1616. for (x = 0; x < w; x++) {
  1617. for (y = 0; y < h; y++) {
  1618. dsf_update_completion(state, x, y, R, dsf);
  1619. dsf_update_completion(state, x, y, D, dsf);
  1620. }
  1621. }
  1622. fls = findloop_new_state(w*h);
  1623. ctx.state = state;
  1624. if (findloop_run(fls, w*h, tracks_neighbour, &ctx)) {
  1625. debug(("loop detected, not complete"));
  1626. ret = false; /* no loop allowed */
  1627. if (mark) {
  1628. for (x = 0; x < w; x++) {
  1629. for (y = 0; y < h; y++) {
  1630. int u, v;
  1631. u = y*w + x;
  1632. for (v = tracks_neighbour(u, &ctx); v >= 0;
  1633. v = tracks_neighbour(-1, &ctx))
  1634. if (findloop_is_loop_edge(fls, u, v))
  1635. state->sflags[y*w+x] |= S_ERROR;
  1636. }
  1637. }
  1638. }
  1639. }
  1640. findloop_free_state(fls);
  1641. if (mark) {
  1642. pathclass = dsf_canonify(dsf, state->numbers->row_s*w);
  1643. if (pathclass == dsf_canonify(dsf, (h-1)*w + state->numbers->col_s)) {
  1644. /* We have a continuous path between the entrance and the exit: any
  1645. other path must be in error. */
  1646. for (i = 0; i < w*h; i++) {
  1647. if ((dsf_canonify(dsf, i) != pathclass) &&
  1648. ((state->sflags[i] & S_TRACK) ||
  1649. (S_E_COUNT(state, i%w, i/w, E_TRACK) > 0))) {
  1650. ret = false;
  1651. state->sflags[i] |= S_ERROR;
  1652. }
  1653. }
  1654. } else {
  1655. /* If we _don't_ have such a path, then certainly the game
  1656. * can't be in a winning state. So even if we're not
  1657. * highlighting any _errors_, we certainly shouldn't
  1658. * return true. */
  1659. ret = false;
  1660. }
  1661. }
  1662. /*
  1663. * A cell is 'complete', for the purposes of marking the game as
  1664. * finished, if it has two edges marked as TRACK. But it only has
  1665. * to have one edge marked as TRACK, or be filled in as trackful
  1666. * without any specific edges known, to count towards checking
  1667. * row/column clue errors.
  1668. *
  1669. * This changes if we haven't found any other errors by this
  1670. * point, so the player has constructed a route from A to B. In
  1671. * that case, we highlight any row/column where the actually laid
  1672. * tracks don't match the clue.
  1673. */
  1674. pathret = ret; /* Do we have a plausible solution so far? */
  1675. for (x = 0; x < w; x++) {
  1676. target = state->numbers->numbers[x];
  1677. ntrack = nnotrack = ntrackcomplete = 0;
  1678. for (y = 0; y < h; y++) {
  1679. if (S_E_COUNT(state, x, y, E_TRACK) > 0 ||
  1680. state->sflags[y*w+x] & S_TRACK)
  1681. ntrack++;
  1682. if (S_E_COUNT(state, x, y, E_TRACK) == 2)
  1683. ntrackcomplete++;
  1684. if (state->sflags[y*w+x] & S_NOTRACK)
  1685. nnotrack++;
  1686. }
  1687. if (mark) {
  1688. if (ntrack > target || nnotrack > (h-target) ||
  1689. (pathret && ntrackcomplete != target)) {
  1690. debug(("col %d error: target %d, track %d, notrack %d, "
  1691. "pathret %d, trackcomplete %d",
  1692. x, target, ntrack, nnotrack, pathret, ntrackcomplete));
  1693. state->num_errors[x] = 1;
  1694. ret = false;
  1695. }
  1696. }
  1697. if (ntrackcomplete != target)
  1698. ret = false;
  1699. }
  1700. for (y = 0; y < h; y++) {
  1701. target = state->numbers->numbers[w+y];
  1702. ntrack = nnotrack = ntrackcomplete = 0;
  1703. for (x = 0; x < w; x++) {
  1704. if (S_E_COUNT(state, x, y, E_TRACK) > 0 ||
  1705. state->sflags[y*w+x] & S_TRACK)
  1706. ntrack++;
  1707. if (S_E_COUNT(state, x, y, E_TRACK) == 2)
  1708. ntrackcomplete++;
  1709. if (state->sflags[y*w+x] & S_NOTRACK)
  1710. nnotrack++;
  1711. }
  1712. if (mark) {
  1713. if (ntrack > target || nnotrack > (w-target) ||
  1714. (pathret && ntrackcomplete != target)) {
  1715. debug(("row %d error: target %d, track %d, notrack %d, "
  1716. "pathret %d, trackcomplete %d",
  1717. y, target, ntrack, nnotrack, pathret, ntrackcomplete));
  1718. state->num_errors[w+y] = 1;
  1719. ret = false;
  1720. }
  1721. }
  1722. if (ntrackcomplete != target)
  1723. ret = false;
  1724. }
  1725. if (mark) {
  1726. state->completed = ret;
  1727. if (ret) set_flash_data(state);
  1728. }
  1729. dsf_free(dsf);
  1730. return ret;
  1731. }
  1732. /* Code borrowed from Pearl. */
  1733. struct game_ui {
  1734. bool dragging, clearing, notrack;
  1735. int drag_sx, drag_sy, drag_ex, drag_ey; /* drag start and end grid coords */
  1736. int clickx, clicky; /* pixel position of initial click */
  1737. int curx, cury; /* grid position of keyboard cursor; uses half-size grid */
  1738. bool cursor_active; /* true iff cursor is shown */
  1739. };
  1740. static game_ui *new_ui(const game_state *state)
  1741. {
  1742. game_ui *ui = snew(game_ui);
  1743. ui->clearing = false;
  1744. ui->notrack = false;
  1745. ui->dragging = false;
  1746. ui->drag_sx = ui->drag_sy = ui->drag_ex = ui->drag_ey = -1;
  1747. ui->cursor_active = getenv_bool("PUZZLES_SHOW_CURSOR", false);
  1748. ui->curx = ui->cury = 1;
  1749. return ui;
  1750. }
  1751. static void free_ui(game_ui *ui)
  1752. {
  1753. sfree(ui);
  1754. }
  1755. static void game_changed_state(game_ui *ui, const game_state *oldstate,
  1756. const game_state *newstate)
  1757. {
  1758. }
  1759. #define PREFERRED_TILE_SIZE 33
  1760. #define HALFSZ (ds->sz6*3)
  1761. #define THIRDSZ (ds->sz6*2)
  1762. #define TILE_SIZE (ds->sz6*6)
  1763. #define MAX_BORDER (TILE_SIZE/8)
  1764. #define LINE_THICK (TILE_SIZE/16)
  1765. #define BORDER (ds->border)
  1766. #define GRID_LINE_TL (ds->grid_line_tl)
  1767. #define GRID_LINE_BR (ds->grid_line_br)
  1768. #define GRID_LINE_ALL (ds->grid_line_all)
  1769. #define COORD(x) ( (x+1) * TILE_SIZE + BORDER )
  1770. #define CENTERED_COORD(x) ( COORD(x) + TILE_SIZE/2 )
  1771. #define FROMCOORD(x) ( ((x) < BORDER) ? -1 : ( ((x) - BORDER) / TILE_SIZE) - 1 )
  1772. #define DS_DSHIFT 4 /* R/U/L/D shift, for drag-in-progress flags */
  1773. #define DS_ERROR (1 << 8)
  1774. #define DS_CLUE (1 << 9)
  1775. #define DS_NOTRACK (1 << 10)
  1776. #define DS_FLASH (1 << 11)
  1777. #define DS_CURSOR (1 << 12) /* cursor in square (centre, or on edge) */
  1778. #define DS_TRACK (1 << 13)
  1779. #define DS_CLEARING (1 << 14)
  1780. #define DS_NSHIFT 16 /* R/U/L/D shift, for no-track edge flags */
  1781. #define DS_CSHIFT 20 /* R/U/L/D shift, for cursor-on-edge */
  1782. struct game_drawstate {
  1783. int sz6, border, grid_line_all, grid_line_tl, grid_line_br;
  1784. bool started;
  1785. int w, h, sz;
  1786. unsigned int *flags, *flags_drag;
  1787. int *num_errors;
  1788. };
  1789. static void update_ui_drag(const game_state *state, game_ui *ui, int gx, int gy)
  1790. {
  1791. int w = state->p.w, h = state->p.h;
  1792. int dx = abs(ui->drag_sx - gx), dy = abs(ui->drag_sy - gy);
  1793. if (dy == 0) {
  1794. ui->drag_ex = gx < 0 ? 0 : gx >= w ? w-1 : gx;
  1795. ui->drag_ey = ui->drag_sy;
  1796. ui->dragging = true;
  1797. } else if (dx == 0) {
  1798. ui->drag_ex = ui->drag_sx;
  1799. ui->drag_ey = gy < 0 ? 0 : gy >= h ? h-1 : gy;
  1800. ui->dragging = true;
  1801. } else {
  1802. ui->drag_ex = ui->drag_sx;
  1803. ui->drag_ey = ui->drag_sy;
  1804. ui->dragging = false;
  1805. }
  1806. }
  1807. static bool ui_can_flip_edge(const game_state *state, int x, int y, int dir,
  1808. bool notrack)
  1809. {
  1810. int w = state->p.w /*, h = state->shared->h, sz = state->shared->sz */;
  1811. int x2 = x + DX(dir);
  1812. int y2 = y + DY(dir);
  1813. unsigned int sf1, sf2, ef;
  1814. if (!INGRID(state, x, y) || !INGRID(state, x2, y2))
  1815. return false;
  1816. sf1 = state->sflags[y*w + x];
  1817. sf2 = state->sflags[y2*w + x2];
  1818. if ( !notrack && ((sf1 & S_CLUE) || (sf2 & S_CLUE)) )
  1819. return false;
  1820. ef = S_E_FLAGS(state, x, y, dir);
  1821. if (notrack) {
  1822. /* if we're going to _set_ NOTRACK (i.e. the flag is currently unset),
  1823. make sure the edge is not already set to TRACK. The adjacent squares
  1824. could be set to TRACK, because we don't know which edges the general
  1825. square setting refers to. */
  1826. if (!(ef & E_NOTRACK) && (ef & E_TRACK))
  1827. return false;
  1828. } else {
  1829. if (!(ef & E_TRACK)) {
  1830. /* if we're going to _set_ TRACK, make sure neither adjacent square nor
  1831. the edge itself is already set to NOTRACK. */
  1832. if ((sf1 & S_NOTRACK) || (sf2 & S_NOTRACK) || (ef & E_NOTRACK))
  1833. return false;
  1834. /* if we're going to _set_ TRACK, make sure neither adjacent square has
  1835. 2 track flags already. */
  1836. if ((S_E_COUNT(state, x, y, E_TRACK) >= 2) ||
  1837. (S_E_COUNT(state, x2, y2, E_TRACK) >= 2))
  1838. return false;
  1839. }
  1840. }
  1841. return true;
  1842. }
  1843. static bool ui_can_flip_square(const game_state *state, int x, int y, bool notrack)
  1844. {
  1845. int w = state->p.w, trackc;
  1846. unsigned sf;
  1847. if (!INGRID(state, x, y)) return false;
  1848. sf = state->sflags[y*w+x];
  1849. trackc = S_E_COUNT(state, x, y, E_TRACK);
  1850. if (sf & S_CLUE) return false;
  1851. if (notrack) {
  1852. /* If we're setting S_NOTRACK, we cannot have either S_TRACK or any E_TRACK. */
  1853. if (!(sf & S_NOTRACK) && ((sf & S_TRACK) || (trackc > 0)))
  1854. return false;
  1855. } else {
  1856. /* If we're setting S_TRACK, we cannot have any S_NOTRACK (we could have
  1857. E_NOTRACK, though, because one or two wouldn't rule out a track) */
  1858. if (!(sf & S_TRACK) && (sf & S_NOTRACK))
  1859. return false;
  1860. }
  1861. return true;
  1862. }
  1863. static const char *current_key_label(const game_ui *ui,
  1864. const game_state *state, int button)
  1865. {
  1866. if (IS_CURSOR_SELECT(button) && ui->cursor_active) {
  1867. int gx = ui->curx / 2, gy = ui->cury / 2;
  1868. int w = state->p.w;
  1869. int direction =
  1870. ((ui->curx % 2) == 0) ? L : ((ui->cury % 2) == 0) ? U : 0;
  1871. if (direction &&
  1872. ui_can_flip_edge(state, gx, gy, direction,
  1873. button == CURSOR_SELECT2)) {
  1874. unsigned ef = S_E_FLAGS(state, gx, gy, direction);
  1875. switch (button) {
  1876. case CURSOR_SELECT: return (ef & E_TRACK) ? "Clear" : "Track";
  1877. case CURSOR_SELECT2: return (ef & E_NOTRACK) ? "Clear" : "X";
  1878. }
  1879. }
  1880. if (!direction &&
  1881. ui_can_flip_square(state, gx, gy, button == CURSOR_SELECT2)) {
  1882. unsigned sf = state->sflags[gy*w+gx];
  1883. switch (button) {
  1884. case CURSOR_SELECT: return (sf & S_TRACK) ? "Clear" : "Track";
  1885. case CURSOR_SELECT2: return (sf & S_NOTRACK) ? "Clear" : "X";
  1886. }
  1887. }
  1888. }
  1889. return "";
  1890. }
  1891. static char *edge_flip_str(const game_state *state, int x, int y, int dir, bool notrack, char *buf) {
  1892. unsigned ef = S_E_FLAGS(state, x, y, dir);
  1893. char c;
  1894. if (notrack)
  1895. c = (ef & E_NOTRACK) ? 'n' : 'N';
  1896. else
  1897. c = (ef & E_TRACK) ? 't' : 'T';
  1898. sprintf(buf, "%c%c%d,%d", c, MOVECHAR(dir), x, y);
  1899. return dupstr(buf);
  1900. }
  1901. static char *square_flip_str(const game_state *state, int x, int y, bool notrack, char *buf) {
  1902. unsigned f = state->sflags[y*state->p.w+x];
  1903. char c;
  1904. if (notrack)
  1905. c = (f & E_NOTRACK) ? 'n' : 'N';
  1906. else
  1907. c = (f & E_TRACK) ? 't' : 'T';
  1908. sprintf(buf, "%cS%d,%d", c, x, y);
  1909. return dupstr(buf);
  1910. }
  1911. #define SIGN(x) ((x<0) ? -1 : (x>0))
  1912. static game_state *copy_and_apply_drag(const game_state *state, const game_ui *ui)
  1913. {
  1914. game_state *after = dup_game(state);
  1915. int x1, y1, x2, y2, x, y, w = state->p.w;
  1916. unsigned f = ui->notrack ? S_NOTRACK : S_TRACK, ff;
  1917. x1 = min(ui->drag_sx, ui->drag_ex); x2 = max(ui->drag_sx, ui->drag_ex);
  1918. y1 = min(ui->drag_sy, ui->drag_ey); y2 = max(ui->drag_sy, ui->drag_ey);
  1919. /* actually either x1 == x2, or y1 == y2, but it's easier just to code
  1920. the nested loop. */
  1921. for (x = x1; x <= x2; x++) {
  1922. for (y = y1; y <= y2; y++) {
  1923. ff = state->sflags[y*w+x];
  1924. if (ui->clearing && !(ff & f))
  1925. continue; /* nothing to do, clearing and already clear */
  1926. else if (!ui->clearing && (ff & f))
  1927. continue; /* nothing to do, setting and already set */
  1928. else if (ui_can_flip_square(state, x, y, ui->notrack))
  1929. after->sflags[y*w+x] ^= f;
  1930. }
  1931. }
  1932. return after;
  1933. }
  1934. #define KEY_DIRECTION(btn) (\
  1935. (btn) == CURSOR_DOWN ? D : (btn) == CURSOR_UP ? U :\
  1936. (btn) == CURSOR_LEFT ? L : R)
  1937. static char *interpret_move(const game_state *state, game_ui *ui,
  1938. const game_drawstate *ds,
  1939. int x, int y, int button)
  1940. {
  1941. int w = state->p.w, h = state->p.h, direction;
  1942. int gx = FROMCOORD(x), gy = FROMCOORD(y);
  1943. char tmpbuf[80];
  1944. /* --- mouse operations --- */
  1945. if (IS_MOUSE_DOWN(button)) {
  1946. ui->cursor_active = false;
  1947. ui->dragging = false;
  1948. if (!INGRID(state, gx, gy)) {
  1949. /* can't drag from off grid */
  1950. ui->drag_sx = ui->drag_sy = -1;
  1951. return NULL;
  1952. }
  1953. if (button == RIGHT_BUTTON) {
  1954. ui->notrack = true;
  1955. ui->clearing = state->sflags[gy*w+gx] & S_NOTRACK;
  1956. } else {
  1957. ui->notrack = false;
  1958. ui->clearing = state->sflags[gy*w+gx] & S_TRACK;
  1959. }
  1960. ui->clickx = x;
  1961. ui->clicky = y;
  1962. ui->drag_sx = ui->drag_ex = gx;
  1963. ui->drag_sy = ui->drag_ey = gy;
  1964. return MOVE_UI_UPDATE;
  1965. }
  1966. if (IS_MOUSE_DRAG(button)) {
  1967. ui->cursor_active = false;
  1968. update_ui_drag(state, ui, gx, gy);
  1969. return MOVE_UI_UPDATE;
  1970. }
  1971. if (IS_MOUSE_RELEASE(button)) {
  1972. ui->cursor_active = false;
  1973. if (ui->dragging &&
  1974. (ui->drag_sx != ui->drag_ex || ui->drag_sy != ui->drag_ey)) {
  1975. game_state *dragged = copy_and_apply_drag(state, ui);
  1976. char *ret = move_string_diff(state, dragged, false);
  1977. ui->dragging = false;
  1978. free_game(dragged);
  1979. return ret;
  1980. } else {
  1981. int cx, cy;
  1982. /* We might still have been dragging (and just done a one-
  1983. * square drag): cancel drag, so undo doesn't make it like
  1984. * a drag-in-progress. */
  1985. ui->dragging = false;
  1986. /* Click (or tiny drag). Work out which edge we were
  1987. * closest to. */
  1988. /*
  1989. * We process clicks based on the mouse-down location,
  1990. * because that's more natural for a user to carefully
  1991. * control than the mouse-up.
  1992. */
  1993. x = ui->clickx;
  1994. y = ui->clicky;
  1995. cx = CENTERED_COORD(gx);
  1996. cy = CENTERED_COORD(gy);
  1997. if (!INGRID(state, gx, gy) || FROMCOORD(x) != gx || FROMCOORD(y) != gy)
  1998. return MOVE_UI_UPDATE;
  1999. if (max(abs(x-cx),abs(y-cy)) < TILE_SIZE/4) {
  2000. if (ui_can_flip_square(state, gx, gy, button == RIGHT_RELEASE))
  2001. return square_flip_str(state, gx, gy, button == RIGHT_RELEASE, tmpbuf);
  2002. return MOVE_UI_UPDATE;
  2003. } else {
  2004. if (abs(x-cx) < abs(y-cy)) {
  2005. /* Closest to top/bottom edge. */
  2006. direction = (y < cy) ? U : D;
  2007. } else {
  2008. /* Closest to left/right edge. */
  2009. direction = (x < cx) ? L : R;
  2010. }
  2011. if (ui_can_flip_edge(state, gx, gy, direction,
  2012. button == RIGHT_RELEASE))
  2013. return edge_flip_str(state, gx, gy, direction,
  2014. button == RIGHT_RELEASE, tmpbuf);
  2015. else
  2016. return MOVE_UI_UPDATE;
  2017. }
  2018. }
  2019. }
  2020. /* --- cursor/keyboard operations --- */
  2021. if (IS_CURSOR_MOVE(button)) {
  2022. int dx = (button == CURSOR_LEFT) ? -1 : ((button == CURSOR_RIGHT) ? +1 : 0);
  2023. int dy = (button == CURSOR_DOWN) ? +1 : ((button == CURSOR_UP) ? -1 : 0);
  2024. if (!ui->cursor_active) {
  2025. ui->cursor_active = true;
  2026. return MOVE_UI_UPDATE;
  2027. }
  2028. ui->curx = ui->curx + dx;
  2029. ui->cury = ui->cury + dy;
  2030. if ((ui->curx % 2 == 0) && (ui->cury % 2 == 0)) {
  2031. /* disallow cursor on square corners: centres and edges only */
  2032. ui->curx += dx; ui->cury += dy;
  2033. }
  2034. ui->curx = min(max(ui->curx, 1), 2*w-1);
  2035. ui->cury = min(max(ui->cury, 1), 2*h-1);
  2036. return MOVE_UI_UPDATE;
  2037. }
  2038. if (IS_CURSOR_SELECT(button)) {
  2039. if (!ui->cursor_active) {
  2040. ui->cursor_active = true;
  2041. return MOVE_UI_UPDATE;
  2042. }
  2043. /* click on square corner does nothing (shouldn't get here) */
  2044. if ((ui->curx % 2) == 0 && (ui->cury % 2 == 0))
  2045. return MOVE_UI_UPDATE;
  2046. gx = ui->curx / 2;
  2047. gy = ui->cury / 2;
  2048. direction = ((ui->curx % 2) == 0) ? L : ((ui->cury % 2) == 0) ? U : 0;
  2049. if (direction &&
  2050. ui_can_flip_edge(state, gx, gy, direction, button == CURSOR_SELECT2))
  2051. return edge_flip_str(state, gx, gy, direction, button == CURSOR_SELECT2, tmpbuf);
  2052. else if (!direction &&
  2053. ui_can_flip_square(state, gx, gy, button == CURSOR_SELECT2))
  2054. return square_flip_str(state, gx, gy, button == CURSOR_SELECT2, tmpbuf);
  2055. return MOVE_UI_UPDATE;
  2056. }
  2057. #if 0
  2058. /* helps to debug the solver */
  2059. if (button == 'H' || button == 'h')
  2060. return dupstr("H");
  2061. #endif
  2062. return NULL;
  2063. }
  2064. static game_state *execute_move(const game_state *state, const char *move)
  2065. {
  2066. int w = state->p.w, x, y, n, i;
  2067. char c, d;
  2068. unsigned f;
  2069. bool move_is_solve = false;
  2070. game_state *ret = dup_game(state);
  2071. /* this is breaking the bank on GTK, which vsprintf's into a fixed-size buffer
  2072. * which is 4096 bytes long. vsnprintf needs a feature-test macro to use, faff. */
  2073. /*debug(("move: %s\n", move));*/
  2074. while (*move) {
  2075. c = *move;
  2076. if (c == 'S') {
  2077. ret->used_solve = true;
  2078. move_is_solve = true;
  2079. move++;
  2080. } else if (c == 'T' || c == 't' || c == 'N' || c == 'n') {
  2081. /* set track, clear track; set notrack, clear notrack */
  2082. move++;
  2083. if (sscanf(move, "%c%d,%d%n", &d, &x, &y, &n) != 3)
  2084. goto badmove;
  2085. if (!INGRID(state, x, y)) goto badmove;
  2086. f = (c == 'T' || c == 't') ? S_TRACK : S_NOTRACK;
  2087. if (d == 'S') {
  2088. if (!ui_can_flip_square(ret, x, y, f == S_NOTRACK) &&
  2089. !move_is_solve)
  2090. goto badmove;
  2091. if (c == 'T' || c == 'N')
  2092. ret->sflags[y*w+x] |= f;
  2093. else
  2094. ret->sflags[y*w+x] &= ~f;
  2095. } else if (d == 'U' || d == 'D' || d == 'L' || d == 'R') {
  2096. for (i = 0; i < 4; i++) {
  2097. unsigned df = 1<<i;
  2098. if (MOVECHAR(df) == d) {
  2099. if (!ui_can_flip_edge(ret, x, y, df, f == S_NOTRACK) &&
  2100. !move_is_solve)
  2101. goto badmove;
  2102. if (c == 'T' || c == 'N')
  2103. S_E_SET(ret, x, y, df, f);
  2104. else
  2105. S_E_CLEAR(ret, x, y, df, f);
  2106. }
  2107. }
  2108. } else
  2109. goto badmove;
  2110. move += n;
  2111. } else if (c == 'H') {
  2112. tracks_solve(ret, DIFFCOUNT, NULL);
  2113. move++;
  2114. } else {
  2115. goto badmove;
  2116. }
  2117. if (*move == ';')
  2118. move++;
  2119. else if (*move)
  2120. goto badmove;
  2121. }
  2122. check_completion(ret, true);
  2123. return ret;
  2124. badmove:
  2125. free_game(ret);
  2126. return NULL;
  2127. }
  2128. /* ----------------------------------------------------------------------
  2129. * Drawing routines.
  2130. */
  2131. #define FLASH_TIME 0.5F
  2132. static void game_compute_size(const game_params *params, int tilesize,
  2133. const game_ui *ui, int *x, int *y)
  2134. {
  2135. /* Ick: fake up `ds->sz6' and `ds->border` for macro expansion purposes */
  2136. struct {
  2137. int sz6, border;
  2138. } ads, *ds = &ads;
  2139. ads.sz6 = tilesize/6;
  2140. ads.border = MAX_BORDER;
  2141. /*
  2142. * Allow a reduced border at small tile sizes because the steps
  2143. * are quite large and it's better to have a thin border than
  2144. * to go down to a smaller tile size.
  2145. */
  2146. if (ads.border <= 5)
  2147. ads.border = min(tilesize % 6, MAX_BORDER);
  2148. *x = (params->w+2) * TILE_SIZE + 2 * BORDER;
  2149. *y = (params->h+2) * TILE_SIZE + 2 * BORDER;
  2150. }
  2151. static void game_set_size(drawing *dr, game_drawstate *ds,
  2152. const game_params *params, int tilesize)
  2153. {
  2154. ds->sz6 = tilesize/6;
  2155. ds->border = MAX_BORDER;
  2156. if (ds->border <= 5)
  2157. ds->border = min(tilesize % 6, MAX_BORDER);
  2158. ds->grid_line_all = max(LINE_THICK, 1);
  2159. ds->grid_line_br = ds->grid_line_all / 2;
  2160. ds->grid_line_tl = ds->grid_line_all - ds->grid_line_br;
  2161. }
  2162. enum {
  2163. COL_BACKGROUND, COL_TRACK_BACKGROUND,
  2164. COL_GRID, COL_CLUE, COL_CURSOR,
  2165. COL_TRACK, COL_TRACK_CLUE, COL_SLEEPER,
  2166. COL_DRAGON, COL_DRAGOFF,
  2167. COL_ERROR, COL_FLASH, COL_ERROR_BACKGROUND,
  2168. NCOLOURS
  2169. };
  2170. static float *game_colours(frontend *fe, int *ncolours)
  2171. {
  2172. float *ret = snewn(3 * NCOLOURS, float);
  2173. int i;
  2174. game_mkhighlight(fe, ret, COL_BACKGROUND, -1, COL_TRACK_BACKGROUND);
  2175. colour_mix(&ret[COL_BACKGROUND*3], &ret[COL_TRACK_BACKGROUND*3], 0.5F,
  2176. &ret[COL_GRID*3]);
  2177. for (i = 0; i < 3; i++) {
  2178. ret[COL_TRACK_CLUE * 3 + i] = 0.0F;
  2179. ret[COL_TRACK * 3 + i] = 0.5F;
  2180. ret[COL_CLUE * 3 + i] = 0.0F;
  2181. ret[COL_CURSOR * 3 + i] = 0.3F;
  2182. ret[COL_ERROR_BACKGROUND * 3 + i] = 1.0F;
  2183. }
  2184. ret[COL_SLEEPER * 3 + 0] = 0.5F;
  2185. ret[COL_SLEEPER * 3 + 1] = 0.4F;
  2186. ret[COL_SLEEPER * 3 + 2] = 0.1F;
  2187. ret[COL_ERROR * 3 + 0] = 1.0F;
  2188. ret[COL_ERROR * 3 + 1] = 0.0F;
  2189. ret[COL_ERROR * 3 + 2] = 0.0F;
  2190. ret[COL_DRAGON * 3 + 0] = 0.0F;
  2191. ret[COL_DRAGON * 3 + 1] = 0.0F;
  2192. ret[COL_DRAGON * 3 + 2] = 1.0F;
  2193. ret[COL_DRAGOFF * 3 + 0] = 0.8F;
  2194. ret[COL_DRAGOFF * 3 + 1] = 0.8F;
  2195. ret[COL_DRAGOFF * 3 + 2] = 1.0F;
  2196. ret[COL_FLASH * 3 + 0] = 1.0F;
  2197. ret[COL_FLASH * 3 + 1] = 1.0F;
  2198. ret[COL_FLASH * 3 + 2] = 1.0F;
  2199. *ncolours = NCOLOURS;
  2200. return ret;
  2201. }
  2202. static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
  2203. {
  2204. struct game_drawstate *ds = snew(struct game_drawstate);
  2205. int i;
  2206. ds->sz6 = 0;
  2207. ds->started = false;
  2208. ds->w = state->p.w;
  2209. ds->h = state->p.h;
  2210. ds->sz = ds->w*ds->h;
  2211. ds->flags = snewn(ds->sz, unsigned int);
  2212. ds->flags_drag = snewn(ds->sz, unsigned int);
  2213. for (i = 0; i < ds->sz; i++)
  2214. ds->flags[i] = ds->flags_drag[i] = 0;
  2215. ds->num_errors = snewn(ds->w+ds->h, int);
  2216. for (i = 0; i < ds->w+ds->h; i++)
  2217. ds->num_errors[i] = 0;
  2218. return ds;
  2219. }
  2220. static void game_free_drawstate(drawing *dr, game_drawstate *ds)
  2221. {
  2222. sfree(ds->flags);
  2223. sfree(ds->flags_drag);
  2224. sfree(ds->num_errors);
  2225. sfree(ds);
  2226. }
  2227. static void draw_circle_sleepers(drawing *dr, game_drawstate *ds,
  2228. float cx, float cy, float r2, float thickness, int c)
  2229. {
  2230. float qr6 = (float)PI/12, qr3 = (float)PI/6, th, x1, y1, x2, y2;
  2231. float t6 = THIRDSZ/2.0F, r1 = t6;
  2232. int i;
  2233. for (i = 0; i < 12; i++) {
  2234. th = qr6 + (i*qr3);
  2235. x1 = r1*(float)cos(th);
  2236. x2 = r2*(float)cos(th);
  2237. y1 = r1*(float)sin(th);
  2238. y2 = r2*(float)sin(th);
  2239. draw_thick_line(dr, thickness, cx+x1, cy+y1, cx+x2, cy+y2, c);
  2240. }
  2241. }
  2242. static void draw_thick_circle_outline(drawing *dr, float thickness,
  2243. float cx, float cy, float r,
  2244. int colour)
  2245. {
  2246. float circ4 = 0.5F * (float)PI * r, ang, x1, y1, x2, y2;
  2247. int i, nseg;
  2248. nseg = (int)(circ4 / 4.0F)*4; /* ensure a quarter-circle has a whole #segs */
  2249. ang = 2.0F*(float)PI / nseg;
  2250. for (i = 0; i < nseg; i++) {
  2251. float th = ang * i, th2 = ang * (i+1);
  2252. x1 = cx + r*(float)cos(th);
  2253. x2 = cx + r*(float)cos(th2);
  2254. y1 = cy + r*(float)sin(th);
  2255. y2 = cy + r*(float)sin(th2);
  2256. debug(("circ outline: x=%.2f -> %.2f, thick=%.2f\n",
  2257. x1, x2, thickness));
  2258. draw_thick_line(dr, thickness, x1, y1, x2, y2, colour);
  2259. }
  2260. }
  2261. static void draw_tracks_specific(drawing *dr, game_drawstate *ds,
  2262. int x, int y, unsigned int flags,
  2263. int ctrack, int csleeper)
  2264. {
  2265. float ox = (float)COORD(x), oy = (float)COORD(y), cx, cy;
  2266. float t1 = (float)TILE_SIZE, t3 = TILE_SIZE/3.0F, t6 = TILE_SIZE/6.0F;
  2267. int d, i;
  2268. float thick_track = TILE_SIZE/8.0F, thick_sleeper = TILE_SIZE/12.0F;
  2269. if (flags == LR) {
  2270. for (i = 1; i <= 7; i+=2) {
  2271. cx = ox + TILE_SIZE/8.0F*i;
  2272. draw_thick_line(dr, thick_sleeper,
  2273. cx, oy+t6, cx, oy+t6+2*t3, csleeper);
  2274. }
  2275. draw_thick_line(dr, thick_track, ox, oy + t3, ox + TILE_SIZE, oy + t3, ctrack);
  2276. draw_thick_line(dr, thick_track, ox, oy + 2*t3, ox + TILE_SIZE, oy + 2*t3, ctrack);
  2277. return;
  2278. }
  2279. if (flags == UD) {
  2280. for (i = 1; i <= 7; i+=2) {
  2281. cy = oy + TILE_SIZE/8.0F*i;
  2282. draw_thick_line(dr, thick_sleeper,
  2283. ox+t6, cy, ox+t6+2*t3, cy, csleeper);
  2284. }
  2285. debug(("vert line: x=%.2f, thick=%.2f", ox + t3, thick_track));
  2286. draw_thick_line(dr, thick_track, ox + t3, oy, ox + t3, oy + TILE_SIZE, ctrack);
  2287. draw_thick_line(dr, thick_track, ox + 2*t3, oy, ox + 2*t3, oy + TILE_SIZE, ctrack);
  2288. return;
  2289. }
  2290. if (flags == UL || flags == DL || flags == UR || flags == DR) {
  2291. cx = (flags & L) ? ox : ox + TILE_SIZE;
  2292. cy = (flags & U) ? oy : oy + TILE_SIZE;
  2293. draw_circle_sleepers(dr, ds, cx, cy, (float)(5*t6), thick_sleeper, csleeper);
  2294. draw_thick_circle_outline(dr, thick_track, (float)cx, (float)cy,
  2295. 2*t3, ctrack);
  2296. draw_thick_circle_outline(dr, thick_track, (float)cx, (float)cy,
  2297. t3, ctrack);
  2298. return;
  2299. }
  2300. for (d = 1; d < 16; d *= 2) {
  2301. float ox1 = 0, ox2 = 0, oy1 = 0, oy2 = 0;
  2302. if (!(flags & d)) continue;
  2303. for (i = 1; i <= 2; i++) {
  2304. if (d == L) {
  2305. ox1 = 0;
  2306. ox2 = thick_track;
  2307. oy1 = oy2 = i*t3;
  2308. } else if (d == R) {
  2309. ox1 = t1;
  2310. ox2 = t1 - thick_track;
  2311. oy1 = oy2 = i*t3;
  2312. } else if (d == U) {
  2313. ox1 = ox2 = i*t3;
  2314. oy1 = 0;
  2315. oy2 = thick_track;
  2316. } else if (d == D) {
  2317. ox1 = ox2 = i*t3;
  2318. oy1 = t1;
  2319. oy2 = t1 - thick_track;
  2320. }
  2321. draw_thick_line(dr, thick_track, ox+ox1, oy+oy1, ox+ox2, oy+oy2, ctrack);
  2322. }
  2323. }
  2324. }
  2325. static unsigned int best_bits(unsigned int flags, unsigned int flags_drag, int *col)
  2326. {
  2327. int nb_orig = nbits[flags & ALLDIR], nb_drag = nbits[flags_drag & ALLDIR];
  2328. if (nb_orig > nb_drag) {
  2329. *col = COL_DRAGOFF;
  2330. return flags & ALLDIR;
  2331. } else if (nb_orig < nb_drag) {
  2332. *col = COL_DRAGON;
  2333. return flags_drag & ALLDIR;
  2334. }
  2335. return flags & ALLDIR; /* same number of bits: no special colour. */
  2336. }
  2337. static void draw_square(drawing *dr, game_drawstate *ds,
  2338. int x, int y, unsigned int flags, unsigned int flags_drag)
  2339. {
  2340. int t2 = HALFSZ, t16 = HALFSZ/4, off;
  2341. int ox = COORD(x), oy = COORD(y), cx = ox + t2, cy = oy + t2, d, c;
  2342. int bg = (flags & DS_TRACK) ? COL_TRACK_BACKGROUND : COL_BACKGROUND;
  2343. unsigned int flags_best;
  2344. assert(dr);
  2345. /* Clip to the grid square. */
  2346. clip(dr, ox, oy, TILE_SIZE, TILE_SIZE);
  2347. /* Clear the square so that it's got an appropriately-sized border
  2348. * in COL_GRID and a central area in the right background colour. */
  2349. best_bits((flags & DS_TRACK) == DS_TRACK,
  2350. (flags_drag & DS_TRACK) == DS_TRACK, &bg);
  2351. draw_rect(dr, ox, oy, TILE_SIZE, TILE_SIZE, COL_GRID);
  2352. draw_rect(dr, ox + GRID_LINE_TL, oy + GRID_LINE_TL,
  2353. TILE_SIZE - GRID_LINE_ALL, TILE_SIZE - GRID_LINE_ALL, bg);
  2354. /* More outlines for clue squares. */
  2355. if (flags & DS_CURSOR) {
  2356. int curx, cury, curw, curh;
  2357. off = t16;
  2358. curx = ox + off; cury = oy + off;
  2359. curw = curh = TILE_SIZE - (2*off) + 1;
  2360. if (flags & (U << DS_CSHIFT)) {
  2361. cury = oy - off; curh = 2*off + 1;
  2362. } else if (flags & (D << DS_CSHIFT)) {
  2363. cury = oy + TILE_SIZE - off; curh = 2*off + 1;
  2364. } else if (flags & (L << DS_CSHIFT)) {
  2365. curx = ox - off; curw = 2*off + 1;
  2366. } else if (flags & (R << DS_CSHIFT)) {
  2367. curx = ox + TILE_SIZE - off; curw = 2*off + 1;
  2368. }
  2369. draw_rect_outline(dr, curx, cury, curw, curh, COL_CURSOR);
  2370. }
  2371. /* Draw tracks themselves */
  2372. c = (flags & DS_ERROR) ? COL_ERROR :
  2373. (flags & DS_FLASH) ? COL_FLASH :
  2374. (flags & DS_CLUE) ? COL_TRACK_CLUE : COL_TRACK;
  2375. flags_best = best_bits(flags, flags_drag, &c);
  2376. draw_tracks_specific(dr, ds, x, y, flags_best, c, COL_SLEEPER);
  2377. /* Draw no-track marks, if present, in square and on edges. */
  2378. c = COL_TRACK;
  2379. flags_best = best_bits((flags & DS_NOTRACK) == DS_NOTRACK,
  2380. (flags_drag & DS_NOTRACK) == DS_NOTRACK, &c);
  2381. if (flags_best) {
  2382. off = HALFSZ/2;
  2383. draw_thick_line(dr, LINE_THICK, cx - off, cy - off, cx + off, cy + off, c);
  2384. draw_thick_line(dr, LINE_THICK, cx - off, cy + off, cx + off, cy - off, c);
  2385. }
  2386. c = COL_TRACK;
  2387. flags_best = best_bits(flags >> DS_NSHIFT, flags_drag >> DS_NSHIFT, &c);
  2388. for (d = 1; d < 16; d *= 2) {
  2389. off = t16;
  2390. cx = ox + t2;
  2391. cy = oy + t2;
  2392. if (flags_best & d) {
  2393. cx += (d == R) ? t2 : (d == L) ? -t2 : 0;
  2394. cy += (d == D) ? t2 : (d == U) ? -t2 : 0;
  2395. draw_thick_line(dr, LINE_THICK, cx - off, cy - off, cx + off, cy + off, c);
  2396. draw_thick_line(dr, LINE_THICK, cx - off, cy + off, cx + off, cy - off, c);
  2397. }
  2398. }
  2399. unclip(dr);
  2400. draw_update(dr, ox, oy, TILE_SIZE, TILE_SIZE);
  2401. }
  2402. static void draw_clue(drawing *dr, game_drawstate *ds, int w, int clue, int i, int col, int bg)
  2403. {
  2404. int cx, cy, tsz = TILE_SIZE/2;
  2405. char buf[20];
  2406. if (i < w) {
  2407. cx = CENTERED_COORD(i);
  2408. cy = CENTERED_COORD(-1);
  2409. } else {
  2410. cx = CENTERED_COORD(w);
  2411. cy = CENTERED_COORD(i-w);
  2412. }
  2413. if (bg >= 0)
  2414. draw_rect(dr, cx - tsz + GRID_LINE_TL, cy - tsz + GRID_LINE_TL,
  2415. TILE_SIZE - GRID_LINE_ALL, TILE_SIZE - GRID_LINE_ALL, bg);
  2416. sprintf(buf, "%d", clue);
  2417. draw_text(dr, cx, cy, FONT_VARIABLE, tsz, ALIGN_VCENTRE|ALIGN_HCENTRE,
  2418. col, buf);
  2419. draw_update(dr, cx - tsz + GRID_LINE_TL, cy - tsz + GRID_LINE_TL,
  2420. TILE_SIZE - GRID_LINE_ALL, TILE_SIZE - GRID_LINE_ALL);
  2421. }
  2422. static void draw_loop_ends(drawing *dr, game_drawstate *ds,
  2423. const game_state *state, int c)
  2424. {
  2425. int tsz = TILE_SIZE/2;
  2426. draw_text(dr, CENTERED_COORD(-1), CENTERED_COORD(state->numbers->row_s),
  2427. FONT_VARIABLE, tsz, ALIGN_VCENTRE|ALIGN_HCENTRE,
  2428. c, "A");
  2429. draw_text(dr, CENTERED_COORD(state->numbers->col_s), CENTERED_COORD(state->p.h),
  2430. FONT_VARIABLE, tsz, ALIGN_VCENTRE|ALIGN_HCENTRE,
  2431. c, "B");
  2432. }
  2433. static unsigned int s2d_flags(const game_state *state, int x, int y, const game_ui *ui)
  2434. {
  2435. unsigned int f;
  2436. int w = state->p.w;
  2437. f = S_E_DIRS(state, x, y, E_TRACK);
  2438. f |= (S_E_DIRS(state, x, y, E_NOTRACK) << DS_NSHIFT);
  2439. if (state->sflags[y*w+x] & S_ERROR)
  2440. f |= DS_ERROR;
  2441. if (state->sflags[y*w+x] & S_CLUE)
  2442. f |= DS_CLUE;
  2443. if (state->sflags[y*w+x] & S_NOTRACK)
  2444. f |= DS_NOTRACK;
  2445. if ((state->sflags[y*w+x] & S_TRACK) || (S_E_COUNT(state, x, y, E_TRACK) > 0))
  2446. f |= DS_TRACK;
  2447. if (ui->cursor_active) {
  2448. if (ui->curx >= x*2 && ui->curx <= (x+1)*2 &&
  2449. ui->cury >= y*2 && ui->cury <= (y+1)*2) {
  2450. f |= DS_CURSOR;
  2451. if (ui->curx == x*2) f |= (L << DS_CSHIFT);
  2452. if (ui->curx == (x+1)*2) f |= (R << DS_CSHIFT);
  2453. if (ui->cury == y*2) f |= (U << DS_CSHIFT);
  2454. if (ui->cury == (y+1)*2) f |= (D << DS_CSHIFT);
  2455. }
  2456. }
  2457. return f;
  2458. }
  2459. static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldstate,
  2460. const game_state *state, int dir, const game_ui *ui,
  2461. float animtime, float flashtime)
  2462. {
  2463. int i, x, y, flashing, w = ds->w, h = ds->h;
  2464. bool force = false;
  2465. game_state *drag_state = NULL;
  2466. if (!ds->started) {
  2467. draw_loop_ends(dr, ds, state, COL_CLUE);
  2468. draw_rect(dr, COORD(0) - GRID_LINE_BR, COORD(0) - GRID_LINE_BR,
  2469. ds->w * TILE_SIZE + GRID_LINE_ALL,
  2470. ds->h * TILE_SIZE + GRID_LINE_ALL, COL_GRID);
  2471. draw_update(dr, 0, 0, (w+2)*TILE_SIZE + 2*BORDER, (h+2)*TILE_SIZE + 2*BORDER);
  2472. ds->started = true;
  2473. force = true;
  2474. }
  2475. for (i = 0; i < w+h; i++) {
  2476. if (force || (state->num_errors[i] != ds->num_errors[i])) {
  2477. ds->num_errors[i] = state->num_errors[i];
  2478. draw_clue(dr, ds, w, state->numbers->numbers[i], i,
  2479. ds->num_errors[i] ? COL_ERROR : COL_CLUE,
  2480. ds->num_errors[i] ? COL_ERROR_BACKGROUND : COL_BACKGROUND);
  2481. }
  2482. }
  2483. if (ui->dragging)
  2484. drag_state = copy_and_apply_drag(state, ui);
  2485. for (x = 0; x < w; x++) {
  2486. for (y = 0; y < h; y++) {
  2487. unsigned int f, f_d;
  2488. flashing = 0;
  2489. if (flashtime > 0) {
  2490. float flashpos =
  2491. (state->sflags[y*w+x] >> S_FLASH_SHIFT & S_FLASH_MASK) /
  2492. (float)S_FLASH_MASK;
  2493. if (flashtime > FLASH_TIME / 2 * flashpos &&
  2494. flashtime <= FLASH_TIME / 2 * (flashpos + 1.0F))
  2495. flashing = DS_FLASH;
  2496. }
  2497. f = s2d_flags(state, x, y, ui) | flashing;
  2498. f_d = drag_state ? s2d_flags(drag_state, x, y, ui) : f;
  2499. if (f != ds->flags[y*w+x] || f_d != ds->flags_drag[y*w+x] || force) {
  2500. ds->flags[y*w+x] = f;
  2501. ds->flags_drag[y*w+x] = f_d;
  2502. draw_square(dr, ds, x, y, f, f_d);
  2503. }
  2504. }
  2505. }
  2506. if (drag_state) free_game(drag_state);
  2507. }
  2508. static float game_anim_length(const game_state *oldstate, const game_state *newstate,
  2509. int dir, game_ui *ui)
  2510. {
  2511. return 0.0F;
  2512. }
  2513. static float game_flash_length(const game_state *oldstate, const game_state *newstate,
  2514. int dir, game_ui *ui)
  2515. {
  2516. if (!oldstate->completed &&
  2517. newstate->completed && !newstate->used_solve)
  2518. return FLASH_TIME;
  2519. else
  2520. return 0.0F;
  2521. }
  2522. static void game_get_cursor_location(const game_ui *ui,
  2523. const game_drawstate *ds,
  2524. const game_state *state,
  2525. const game_params *params,
  2526. int *x, int *y, int *w, int *h)
  2527. {
  2528. if(ui->cursor_active) {
  2529. int off = HALFSZ / 4;
  2530. int cx = COORD(ui->curx / 2) + off;
  2531. int cy = COORD(ui->cury / 2) + off;
  2532. int cw, ch;
  2533. cw = ch = TILE_SIZE - (2*off) + 1;
  2534. if(ui->curx % 2 == 0) {
  2535. /* left border */
  2536. cx -= off;
  2537. cw = 2 * off + 1;
  2538. }
  2539. if(ui->cury % 2 == 0) {
  2540. /* upper border */
  2541. cy -= off;
  2542. ch = 2 * off + 1;
  2543. }
  2544. *x = cx;
  2545. *y = cy;
  2546. *w = cw;
  2547. *h = ch;
  2548. }
  2549. }
  2550. static int game_status(const game_state *state)
  2551. {
  2552. return state->completed ? +1 : 0;
  2553. }
  2554. static void game_print_size(const game_params *params, const game_ui *ui,
  2555. float *x, float *y)
  2556. {
  2557. int pw, ph;
  2558. /* The Times uses 7mm squares */
  2559. game_compute_size(params, 700, ui, &pw, &ph);
  2560. *x = pw / 100.0F;
  2561. *y = ph / 100.0F;
  2562. }
  2563. static void game_print(drawing *dr, const game_state *state, const game_ui *ui,
  2564. int tilesize)
  2565. {
  2566. int w = state->p.w, h = state->p.h;
  2567. int black = print_mono_colour(dr, 0), grey = print_grey_colour(dr, 0.5F);
  2568. int x, y, i;
  2569. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  2570. game_drawstate ads, *ds = &ads;
  2571. game_set_size(dr, ds, NULL, tilesize);
  2572. /* Grid, then border (second so it is on top) */
  2573. print_line_width(dr, TILE_SIZE / 24);
  2574. for (x = 1; x < w; x++)
  2575. draw_line(dr, COORD(x), COORD(0), COORD(x), COORD(h), grey);
  2576. for (y = 1; y < h; y++)
  2577. draw_line(dr, COORD(0), COORD(y), COORD(w), COORD(y), grey);
  2578. print_line_width(dr, TILE_SIZE / 16);
  2579. draw_rect_outline(dr, COORD(0), COORD(0), w*TILE_SIZE, h*TILE_SIZE, black);
  2580. print_line_width(dr, TILE_SIZE / 24);
  2581. /* clue numbers, and loop ends */
  2582. for (i = 0; i < w+h; i++)
  2583. draw_clue(dr, ds, w, state->numbers->numbers[i], i, black, -1);
  2584. draw_loop_ends(dr, ds, state, black);
  2585. /* clue tracks / solution */
  2586. for (x = 0; x < w; x++) {
  2587. for (y = 0; y < h; y++) {
  2588. clip(dr, COORD(x), COORD(y), TILE_SIZE, TILE_SIZE);
  2589. draw_tracks_specific(dr, ds, x, y, S_E_DIRS(state, x, y, E_TRACK),
  2590. black, grey);
  2591. unclip(dr);
  2592. }
  2593. }
  2594. }
  2595. #ifdef COMBINED
  2596. #define thegame tracks
  2597. #endif
  2598. const struct game thegame = {
  2599. "Train Tracks", "games.tracks", "tracks",
  2600. default_params,
  2601. game_fetch_preset, NULL,
  2602. decode_params,
  2603. encode_params,
  2604. free_params,
  2605. dup_params,
  2606. true, game_configure, custom_params,
  2607. validate_params,
  2608. new_game_desc,
  2609. validate_desc,
  2610. new_game,
  2611. dup_game,
  2612. free_game,
  2613. true, solve_game,
  2614. true, game_can_format_as_text_now, game_text_format,
  2615. NULL, NULL, /* get_prefs, set_prefs */
  2616. new_ui,
  2617. free_ui,
  2618. NULL, /* encode_ui */
  2619. NULL, /* decode_ui */
  2620. NULL, /* game_request_keys */
  2621. game_changed_state,
  2622. current_key_label,
  2623. interpret_move,
  2624. execute_move,
  2625. PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
  2626. game_colours,
  2627. game_new_drawstate,
  2628. game_free_drawstate,
  2629. game_redraw,
  2630. game_anim_length,
  2631. game_flash_length,
  2632. game_get_cursor_location,
  2633. game_status,
  2634. true, false, game_print_size, game_print,
  2635. false, /* wants_statusbar */
  2636. false, NULL, /* timing_state */
  2637. 0, /* flags */
  2638. };
  2639. #ifdef STANDALONE_SOLVER
  2640. int main(int argc, char **argv)
  2641. {
  2642. game_params *p;
  2643. game_state *s;
  2644. char *id = NULL, *desc;
  2645. int maxdiff = DIFFCOUNT, diff_used;
  2646. const char *err;
  2647. bool diagnostics = false, grade = false;
  2648. int retd;
  2649. while (--argc > 0) {
  2650. char *p = *++argv;
  2651. if (!strcmp(p, "-v")) {
  2652. diagnostics = true;
  2653. } else if (!strcmp(p, "-g")) {
  2654. grade = true;
  2655. } else if (!strncmp(p, "-d", 2) && p[2] && !p[3]) {
  2656. int i;
  2657. bool bad = true;
  2658. for (i = 0; i < lenof(tracks_diffchars); i++)
  2659. if (tracks_diffchars[i] == p[2]) {
  2660. bad = false;
  2661. maxdiff = i;
  2662. break;
  2663. }
  2664. if (bad) {
  2665. fprintf(stderr, "%s: unrecognised difficulty `%c'\n",
  2666. argv[0], p[2]);
  2667. return 1;
  2668. }
  2669. } else if (*p == '-') {
  2670. fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
  2671. return 1;
  2672. } else {
  2673. id = p;
  2674. }
  2675. }
  2676. if (!id) {
  2677. fprintf(stderr, "usage: %s [-v | -g] <game_id>\n", argv[0]);
  2678. return 1;
  2679. }
  2680. desc = strchr(id, ':');
  2681. if (!desc) {
  2682. fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]);
  2683. return 1;
  2684. }
  2685. *desc++ = '\0';
  2686. p = default_params();
  2687. decode_params(p, id);
  2688. err = validate_desc(p, desc);
  2689. if (err) {
  2690. fprintf(stderr, "%s: %s\n", argv[0], err);
  2691. return 1;
  2692. }
  2693. s = new_game(NULL, p, desc);
  2694. solver_diagnostics_fp = (diagnostics ? stdout : NULL);
  2695. retd = tracks_solve(s, maxdiff, &diff_used);
  2696. if (retd < 0) {
  2697. printf("Puzzle is inconsistent\n");
  2698. } else if (grade) {
  2699. printf("Difficulty rating: %s\n",
  2700. (retd == 0 ? "Ambiguous" : tracks_diffnames[diff_used]));
  2701. } else {
  2702. char *text = game_text_format(s);
  2703. fputs(text, stdout);
  2704. sfree(text);
  2705. if (retd == 0)
  2706. printf("Could not deduce a unique solution\n");
  2707. }
  2708. free_game(s);
  2709. free_params(p);
  2710. return 0;
  2711. }
  2712. #endif
  2713. /* vim: set shiftwidth=4 tabstop=8: */