net.c 98 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344
  1. /*
  2. * net.c: Net game.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <ctype.h>
  9. #include <limits.h>
  10. #ifdef NO_TGMATH_H
  11. # include <math.h>
  12. #else
  13. # include <tgmath.h>
  14. #endif
  15. #include "puzzles.h"
  16. #include "tree234.h"
  17. /*
  18. * The standard user interface for Net simply has left- and
  19. * right-button mouse clicks in a square rotate it one way or the
  20. * other. We also provide, by #ifdef, a separate interface based on
  21. * rotational dragging motions. I initially developed this for the
  22. * Mac on the basis that it might work better than the click
  23. * interface with only one mouse button available, but in fact
  24. * found it to be quite strange and unintuitive. Apparently it
  25. * works better on stylus-driven platforms such as Palm and
  26. * PocketPC, though, so we enable it by default there.
  27. */
  28. #ifdef STYLUS_BASED
  29. #define USE_DRAGGING
  30. #endif
  31. /* Direction and other bitfields */
  32. #define R 0x01
  33. #define U 0x02
  34. #define L 0x04
  35. #define D 0x08
  36. #define LOCKED 0x10
  37. #define ACTIVE 0x20
  38. #define RERR (R << 6)
  39. #define UERR (U << 6)
  40. #define LERR (L << 6)
  41. #define DERR (D << 6)
  42. #define ERR(dir) ((dir) << 6)
  43. /* Rotations: Anticlockwise, Clockwise, Flip, general rotate */
  44. #define A(x) ( (((x) & 0x07) << 1) | (((x) & 0x08) >> 3) )
  45. #define C(x) ( (((x) & 0x0E) >> 1) | (((x) & 0x01) << 3) )
  46. #define F(x) ( (((x) & 0x0C) >> 2) | (((x) & 0x03) << 2) )
  47. #define ROT(x, n) ( ((n)&3) == 0 ? (x) : \
  48. ((n)&3) == 1 ? A(x) : \
  49. ((n)&3) == 2 ? F(x) : C(x) )
  50. /* X and Y displacements */
  51. #define X(x) ( (x) == R ? +1 : (x) == L ? -1 : 0 )
  52. #define Y(x) ( (x) == D ? +1 : (x) == U ? -1 : 0 )
  53. /* Bit count */
  54. #define COUNT(x) ( (((x) & 0x08) >> 3) + (((x) & 0x04) >> 2) + \
  55. (((x) & 0x02) >> 1) + ((x) & 0x01) )
  56. #define PREFERRED_TILE_SIZE 32
  57. #define TILE_SIZE (ds->tilesize)
  58. #define LINE_THICK ((TILE_SIZE+47)/48)
  59. #ifdef SMALL_SCREEN
  60. #define WINDOW_OFFSET 4
  61. #else
  62. #define WINDOW_OFFSET 16
  63. #endif
  64. #define ROTATE_TIME 0.13F
  65. #define FLASH_FRAME 0.07F
  66. enum {
  67. COL_BACKGROUND,
  68. COL_LOCKED,
  69. COL_BORDER,
  70. COL_WIRE,
  71. COL_ENDPOINT,
  72. COL_POWERED,
  73. COL_BARRIER,
  74. COL_ERR,
  75. NCOLOURS
  76. };
  77. struct game_params {
  78. int width;
  79. int height;
  80. bool wrapping;
  81. bool unique;
  82. float barrier_probability;
  83. };
  84. typedef struct game_immutable_state {
  85. int refcount;
  86. unsigned char *barriers;
  87. } game_immutable_state;
  88. struct game_state {
  89. int width, height;
  90. bool wrapping, completed;
  91. int last_rotate_x, last_rotate_y, last_rotate_dir;
  92. bool used_solve;
  93. unsigned char *tiles;
  94. struct game_immutable_state *imm;
  95. };
  96. #define OFFSETWH(x2,y2,x1,y1,dir,width,height) \
  97. ( (x2) = ((x1) + width + X((dir))) % width, \
  98. (y2) = ((y1) + height + Y((dir))) % height)
  99. #define OFFSET(x2,y2,x1,y1,dir,state) \
  100. OFFSETWH(x2,y2,x1,y1,dir,(state)->width,(state)->height)
  101. #define index(state, a, x, y) ( a[(y) * (state)->width + (x)] )
  102. #define tile(state, x, y) index(state, (state)->tiles, x, y)
  103. #define barrier(state, x, y) index(state, (state)->imm->barriers, x, y)
  104. struct xyd {
  105. int x, y, direction;
  106. };
  107. static int xyd_cmp(const void *av, const void *bv) {
  108. const struct xyd *a = (const struct xyd *)av;
  109. const struct xyd *b = (const struct xyd *)bv;
  110. if (a->x < b->x)
  111. return -1;
  112. if (a->x > b->x)
  113. return +1;
  114. if (a->y < b->y)
  115. return -1;
  116. if (a->y > b->y)
  117. return +1;
  118. if (a->direction < b->direction)
  119. return -1;
  120. if (a->direction > b->direction)
  121. return +1;
  122. return 0;
  123. }
  124. static int xyd_cmp_nc(void *av, void *bv) { return xyd_cmp(av, bv); }
  125. static struct xyd *new_xyd(int x, int y, int direction)
  126. {
  127. struct xyd *xyd = snew(struct xyd);
  128. xyd->x = x;
  129. xyd->y = y;
  130. xyd->direction = direction;
  131. return xyd;
  132. }
  133. /* ----------------------------------------------------------------------
  134. * Manage game parameters.
  135. */
  136. static game_params *default_params(void)
  137. {
  138. game_params *ret = snew(game_params);
  139. ret->width = 5;
  140. ret->height = 5;
  141. ret->wrapping = false;
  142. ret->unique = true;
  143. ret->barrier_probability = 0.0;
  144. return ret;
  145. }
  146. static const struct game_params net_presets[] = {
  147. {5, 5, false, true, 0.0},
  148. {7, 7, false, true, 0.0},
  149. {9, 9, false, true, 0.0},
  150. {11, 11, false, true, 0.0},
  151. #ifndef SMALL_SCREEN
  152. {13, 11, false, true, 0.0},
  153. #endif
  154. {5, 5, true, true, 0.0},
  155. {7, 7, true, true, 0.0},
  156. {9, 9, true, true, 0.0},
  157. {11, 11, true, true, 0.0},
  158. #ifndef SMALL_SCREEN
  159. {13, 11, true, true, 0.0},
  160. #endif
  161. };
  162. static bool game_fetch_preset(int i, char **name, game_params **params)
  163. {
  164. game_params *ret;
  165. char str[80];
  166. if (i < 0 || i >= lenof(net_presets))
  167. return false;
  168. ret = snew(game_params);
  169. *ret = net_presets[i];
  170. sprintf(str, "%dx%d%s", ret->width, ret->height,
  171. ret->wrapping ? " wrapping" : "");
  172. *name = dupstr(str);
  173. *params = ret;
  174. return true;
  175. }
  176. static void free_params(game_params *params)
  177. {
  178. sfree(params);
  179. }
  180. static game_params *dup_params(const game_params *params)
  181. {
  182. game_params *ret = snew(game_params);
  183. *ret = *params; /* structure copy */
  184. return ret;
  185. }
  186. static void decode_params(game_params *ret, char const *string)
  187. {
  188. char const *p = string;
  189. ret->width = atoi(p);
  190. while (*p && isdigit((unsigned char)*p)) p++;
  191. if (*p == 'x') {
  192. p++;
  193. ret->height = atoi(p);
  194. while (*p && isdigit((unsigned char)*p)) p++;
  195. } else {
  196. ret->height = ret->width;
  197. }
  198. while (*p) {
  199. if (*p == 'w') {
  200. p++;
  201. ret->wrapping = true;
  202. } else if (*p == 'b') {
  203. p++;
  204. ret->barrier_probability = (float)atof(p);
  205. while (*p && (*p == '.' || isdigit((unsigned char)*p))) p++;
  206. } else if (*p == 'a') {
  207. p++;
  208. ret->unique = false;
  209. } else
  210. p++; /* skip any other gunk */
  211. }
  212. }
  213. static char *encode_params(const game_params *params, bool full)
  214. {
  215. char ret[400];
  216. int len;
  217. len = sprintf(ret, "%dx%d", params->width, params->height);
  218. if (params->wrapping)
  219. ret[len++] = 'w';
  220. if (full && params->barrier_probability)
  221. len += sprintf(ret+len, "b%g", params->barrier_probability);
  222. if (full && !params->unique)
  223. ret[len++] = 'a';
  224. assert(len < lenof(ret));
  225. ret[len] = '\0';
  226. return dupstr(ret);
  227. }
  228. static config_item *game_configure(const game_params *params)
  229. {
  230. config_item *ret;
  231. char buf[80];
  232. ret = snewn(6, config_item);
  233. ret[0].name = "Width";
  234. ret[0].type = C_STRING;
  235. sprintf(buf, "%d", params->width);
  236. ret[0].u.string.sval = dupstr(buf);
  237. ret[1].name = "Height";
  238. ret[1].type = C_STRING;
  239. sprintf(buf, "%d", params->height);
  240. ret[1].u.string.sval = dupstr(buf);
  241. ret[2].name = "Walls wrap around";
  242. ret[2].type = C_BOOLEAN;
  243. ret[2].u.boolean.bval = params->wrapping;
  244. ret[3].name = "Barrier probability";
  245. ret[3].type = C_STRING;
  246. sprintf(buf, "%g", params->barrier_probability);
  247. ret[3].u.string.sval = dupstr(buf);
  248. ret[4].name = "Ensure unique solution";
  249. ret[4].type = C_BOOLEAN;
  250. ret[4].u.boolean.bval = params->unique;
  251. ret[5].name = NULL;
  252. ret[5].type = C_END;
  253. return ret;
  254. }
  255. static game_params *custom_params(const config_item *cfg)
  256. {
  257. game_params *ret = snew(game_params);
  258. ret->width = atoi(cfg[0].u.string.sval);
  259. ret->height = atoi(cfg[1].u.string.sval);
  260. ret->wrapping = cfg[2].u.boolean.bval;
  261. ret->barrier_probability = (float)atof(cfg[3].u.string.sval);
  262. ret->unique = cfg[4].u.boolean.bval;
  263. return ret;
  264. }
  265. static const char *validate_params(const game_params *params, bool full)
  266. {
  267. if (params->width <= 0 || params->height <= 0)
  268. return "Width and height must both be greater than zero";
  269. if (params->width <= 1 && params->height <= 1)
  270. return "At least one of width and height must be greater than one";
  271. if (params->width > INT_MAX / params->height)
  272. return "Width times height must not be unreasonably large";
  273. if (params->barrier_probability < 0)
  274. return "Barrier probability may not be negative";
  275. if (params->barrier_probability > 1)
  276. return "Barrier probability may not be greater than 1";
  277. /*
  278. * Specifying either grid dimension as 2 in a wrapping puzzle
  279. * makes it actually impossible to ensure a unique puzzle
  280. * solution.
  281. *
  282. * Proof:
  283. *
  284. * Without loss of generality, let us assume the puzzle _width_
  285. * is 2, so we can conveniently discuss rows without having to
  286. * say `rows/columns' all the time. (The height may be 2 as
  287. * well, but that doesn't matter.)
  288. *
  289. * In each row, there are two edges between tiles: the inner
  290. * edge (running down the centre of the grid) and the outer
  291. * edge (the identified left and right edges of the grid).
  292. *
  293. * Lemma: In any valid 2xn puzzle there must be at least one
  294. * row in which _exactly one_ of the inner edge and outer edge
  295. * is connected.
  296. *
  297. * Proof: No row can have _both_ inner and outer edges
  298. * connected, because this would yield a loop. So the only
  299. * other way to falsify the lemma is for every row to have
  300. * _neither_ the inner nor outer edge connected. But this
  301. * means there is no connection at all between the left and
  302. * right columns of the puzzle, so there are two disjoint
  303. * subgraphs, which is also disallowed. []
  304. *
  305. * Given such a row, it is always possible to make the
  306. * disconnected edge connected and the connected edge
  307. * disconnected without changing the state of any other edge.
  308. * (This is easily seen by case analysis on the various tiles:
  309. * left-pointing and right-pointing endpoints can be exchanged,
  310. * likewise T-pieces, and a corner piece can select its
  311. * horizontal connectivity independently of its vertical.) This
  312. * yields a distinct valid solution.
  313. *
  314. * Thus, for _every_ row in which exactly one of the inner and
  315. * outer edge is connected, there are two valid states for that
  316. * row, and hence the total number of solutions of the puzzle
  317. * is at least 2^(number of such rows), and in particular is at
  318. * least 2 since there must be at least one such row. []
  319. */
  320. if (full && params->unique && params->wrapping &&
  321. (params->width == 2 || params->height == 2))
  322. return "No wrapping puzzle with a width or height of 2 can have"
  323. " a unique solution";
  324. return NULL;
  325. }
  326. /* ----------------------------------------------------------------------
  327. * Solver used to assure solution uniqueness during generation.
  328. */
  329. /*
  330. * Test cases I used while debugging all this were
  331. *
  332. * ./net --generate 1 13x11w#12300
  333. * which expands under the non-unique grid generation rules to
  334. * 13x11w:5eaade1bd222664436d5e2965c12656b1129dd825219e3274d558d5eb2dab5da18898e571d5a2987be79746bd95726c597447d6da96188c513add829da7681da954db113d3cd244
  335. * and has two ambiguous areas.
  336. *
  337. * An even better one is
  338. * 13x11w#507896411361192
  339. * which expands to
  340. * 13x11w:b7125b1aec598eb31bd58d82572bc11494e5dee4e8db2bdd29b88d41a16bdd996d2996ddec8c83741a1e8674e78328ba71737b8894a9271b1cd1399453d1952e43951d9b712822e
  341. * and has an ambiguous area _and_ a situation where loop avoidance
  342. * is a necessary deductive technique.
  343. *
  344. * Then there's
  345. * 48x25w#820543338195187
  346. * becoming
  347. * 48x25w:255989d14cdd185deaa753a93821a12edc1ab97943ac127e2685d7b8b3c48861b2192416139212b316eddd35de43714ebc7628d753db32e596284d9ec52c5a7dc1b4c811a655117d16dc28921b2b4161352cab1d89d18bc836b8b891d55ea4622a1251861b5bc9a8aa3e5bcd745c95229ca6c3b5e21d5832d397e917325793d7eb442dc351b2db2a52ba8e1651642275842d8871d5534aabc6d5b741aaa2d48ed2a7dbbb3151ddb49d5b9a7ed1ab98ee75d613d656dbba347bc514c84556b43a9bc65a3256ead792488b862a9d2a8a39b4255a4949ed7dbd79443292521265896b4399c95ede89d7c8c797a6a57791a849adea489359a158aa12e5dacce862b8333b7ebea7d344d1a3c53198864b73a9dedde7b663abb1b539e1e8853b1b7edb14a2a17ebaae4dbe63598a2e7e9a2dbdad415bc1d8cb88cbab5a8c82925732cd282e641ea3bd7d2c6e776de9117a26be86deb7c82c89524b122cb9397cd1acd2284e744ea62b9279bae85479ababe315c3ac29c431333395b24e6a1e3c43a2da42d4dce84aadd5b154aea555eaddcbd6e527d228c19388d9b424d94214555a7edbdeebe569d4a56dc51a86bd9963e377bb74752bd5eaa5761ba545e297b62a1bda46ab4aee423ad6c661311783cc18786d4289236563cb4a75ec67d481c14814994464cd1b87396dee63e5ab6e952cc584baa1d4c47cb557ec84dbb63d487c8728118673a166846dd3a4ebc23d6cb9c5827d96b4556e91899db32b517eda815ae271a8911bd745447121dc8d321557bc2a435ebec1bbac35b1a291669451174e6aa2218a4a9c5a6ca31ebc45d84e3a82c121e9ced7d55e9a
  348. * which has a spot (far right) where slightly more complex loop
  349. * avoidance is required.
  350. */
  351. struct todo {
  352. bool *marked;
  353. int *buffer;
  354. int buflen;
  355. int head, tail;
  356. };
  357. static struct todo *todo_new(int maxsize)
  358. {
  359. struct todo *todo = snew(struct todo);
  360. todo->marked = snewn(maxsize, bool);
  361. memset(todo->marked, 0, maxsize);
  362. todo->buflen = maxsize + 1;
  363. todo->buffer = snewn(todo->buflen, int);
  364. todo->head = todo->tail = 0;
  365. return todo;
  366. }
  367. static void todo_free(struct todo *todo)
  368. {
  369. sfree(todo->marked);
  370. sfree(todo->buffer);
  371. sfree(todo);
  372. }
  373. static void todo_add(struct todo *todo, int index)
  374. {
  375. if (todo->marked[index])
  376. return; /* already on the list */
  377. todo->marked[index] = true;
  378. todo->buffer[todo->tail++] = index;
  379. if (todo->tail == todo->buflen)
  380. todo->tail = 0;
  381. }
  382. static int todo_get(struct todo *todo) {
  383. int ret;
  384. if (todo->head == todo->tail)
  385. return -1; /* list is empty */
  386. ret = todo->buffer[todo->head++];
  387. if (todo->head == todo->buflen)
  388. todo->head = 0;
  389. todo->marked[ret] = false;
  390. return ret;
  391. }
  392. /*
  393. * Return values: -1 means puzzle was proved inconsistent, 0 means we
  394. * failed to narrow down to a unique solution, +1 means we solved it
  395. * fully.
  396. */
  397. static int net_solver(int w, int h, unsigned char *tiles,
  398. unsigned char *barriers, bool wrapping)
  399. {
  400. unsigned char *tilestate;
  401. unsigned char *edgestate;
  402. int *deadends;
  403. DSF *equivalence;
  404. struct todo *todo;
  405. int i, j, x, y;
  406. int area;
  407. bool done_something;
  408. /*
  409. * Set up the solver's data structures.
  410. */
  411. /*
  412. * tilestate stores the possible orientations of each tile.
  413. * There are up to four of these, so we'll index the array in
  414. * fours. tilestate[(y * w + x) * 4] and its three successive
  415. * members give the possible orientations, clearing to 255 from
  416. * the end as things are ruled out.
  417. *
  418. * In this loop we also count up the area of the grid (which is
  419. * not _necessarily_ equal to w*h, because there might be one
  420. * or more blank squares present. This will never happen in a
  421. * grid generated _by_ this program, but it's worth keeping the
  422. * solver as general as possible.)
  423. */
  424. tilestate = snewn(w * h * 4, unsigned char);
  425. area = 0;
  426. for (i = 0; i < w*h; i++) {
  427. tilestate[i * 4] = tiles[i] & 0xF;
  428. for (j = 1; j < 4; j++) {
  429. if (tilestate[i * 4 + j - 1] == 255 ||
  430. A(tilestate[i * 4 + j - 1]) == tilestate[i * 4])
  431. tilestate[i * 4 + j] = 255;
  432. else
  433. tilestate[i * 4 + j] = A(tilestate[i * 4 + j - 1]);
  434. }
  435. if (tiles[i] != 0)
  436. area++;
  437. }
  438. /*
  439. * edgestate stores the known state of each edge. It is 0 for
  440. * unknown, 1 for open (connected) and 2 for closed (not
  441. * connected).
  442. *
  443. * In principle we need only worry about each edge once each,
  444. * but in fact it's easier to track each edge twice so that we
  445. * can reference it from either side conveniently. Also I'm
  446. * going to allocate _five_ bytes per tile, rather than the
  447. * obvious four, so that I can index edgestate[(y*w+x) * 5 + d]
  448. * where d is 1,2,4,8 and they never overlap.
  449. */
  450. edgestate = snewn((w * h - 1) * 5 + 9, unsigned char);
  451. memset(edgestate, 0, (w * h - 1) * 5 + 9);
  452. /*
  453. * deadends tracks which edges have dead ends on them. It is
  454. * indexed by tile and direction: deadends[(y*w+x) * 5 + d]
  455. * tells you whether heading out of tile (x,y) in direction d
  456. * can reach a limited amount of the grid. Values are area+1
  457. * (no dead end known) or less than that (can reach _at most_
  458. * this many other tiles by heading this way out of this tile).
  459. */
  460. deadends = snewn((w * h - 1) * 5 + 9, int);
  461. for (i = 0; i < (w * h - 1) * 5 + 9; i++)
  462. deadends[i] = area+1;
  463. /*
  464. * equivalence tracks which sets of tiles are known to be
  465. * connected to one another, so we can avoid creating loops by
  466. * linking together tiles which are already linked through
  467. * another route.
  468. *
  469. * This is a disjoint set forest structure: equivalence[i]
  470. * contains the index of another member of the equivalence
  471. * class containing i, or contains i itself for precisely one
  472. * member in each such class. To find a representative member
  473. * of the equivalence class containing i, you keep replacing i
  474. * with equivalence[i] until it stops changing; then you go
  475. * _back_ along the same path and point everything on it
  476. * directly at the representative member so as to speed up
  477. * future searches. Then you test equivalence between tiles by
  478. * finding the representative of each tile and seeing if
  479. * they're the same; and you create new equivalence (merge
  480. * classes) by finding the representative of each tile and
  481. * setting equivalence[one]=the_other.
  482. */
  483. equivalence = dsf_new(w * h);
  484. /*
  485. * On a non-wrapping grid, we instantly know that all the edges
  486. * round the edge are closed.
  487. */
  488. if (!wrapping) {
  489. for (i = 0; i < w; i++) {
  490. edgestate[i * 5 + 2] = edgestate[((h-1) * w + i) * 5 + 8] = 2;
  491. }
  492. for (i = 0; i < h; i++) {
  493. edgestate[(i * w + w-1) * 5 + 1] = edgestate[(i * w) * 5 + 4] = 2;
  494. }
  495. }
  496. /*
  497. * If we have barriers available, we can mark those edges as
  498. * closed too.
  499. */
  500. if (barriers) {
  501. for (y = 0; y < h; y++) for (x = 0; x < w; x++) {
  502. int d;
  503. for (d = 1; d <= 8; d += d) {
  504. if (barriers[y*w+x] & d) {
  505. int x2, y2;
  506. /*
  507. * In principle the barrier list should already
  508. * contain each barrier from each side, but
  509. * let's not take chances with our internal
  510. * consistency.
  511. */
  512. OFFSETWH(x2, y2, x, y, d, w, h);
  513. edgestate[(y*w+x) * 5 + d] = 2;
  514. edgestate[(y2*w+x2) * 5 + F(d)] = 2;
  515. }
  516. }
  517. }
  518. }
  519. /*
  520. * Since most deductions made by this solver are local (the
  521. * exception is loop avoidance, where joining two tiles
  522. * together on one side of the grid can theoretically permit a
  523. * fresh deduction on the other), we can address the scaling
  524. * problem inherent in iterating repeatedly over the entire
  525. * grid by instead working with a to-do list.
  526. */
  527. todo = todo_new(w * h);
  528. /*
  529. * Main deductive loop.
  530. */
  531. done_something = true; /* prevent instant termination! */
  532. while (1) {
  533. int index;
  534. /*
  535. * Take a tile index off the todo list and process it.
  536. */
  537. index = todo_get(todo);
  538. if (index == -1) {
  539. /*
  540. * If we have run out of immediate things to do, we
  541. * have no choice but to scan the whole grid for
  542. * longer-range things we've missed. Hence, I now add
  543. * every square on the grid back on to the to-do list.
  544. * I also set `done_something' to false at this point;
  545. * if we later come back here and find it still false,
  546. * we will know we've scanned the entire grid without
  547. * finding anything new to do, and we can terminate.
  548. */
  549. if (!done_something)
  550. break;
  551. for (i = 0; i < w*h; i++)
  552. todo_add(todo, i);
  553. done_something = false;
  554. index = todo_get(todo);
  555. }
  556. y = index / w;
  557. x = index % w;
  558. {
  559. int d, ourclass = dsf_canonify(equivalence, y*w+x);
  560. int deadendmax[9];
  561. deadendmax[1] = deadendmax[2] = deadendmax[4] = deadendmax[8] = 0;
  562. for (i = j = 0; i < 4 && tilestate[(y*w+x) * 4 + i] != 255; i++) {
  563. bool valid;
  564. int nnondeadends, nondeadends[4], deadendtotal;
  565. int nequiv, equiv[5];
  566. int val = tilestate[(y*w+x) * 4 + i];
  567. valid = true;
  568. nnondeadends = deadendtotal = 0;
  569. equiv[0] = ourclass;
  570. nequiv = 1;
  571. for (d = 1; d <= 8; d += d) {
  572. /*
  573. * Immediately rule out this orientation if it
  574. * conflicts with any known edge.
  575. */
  576. if ((edgestate[(y*w+x) * 5 + d] == 1 && !(val & d)) ||
  577. (edgestate[(y*w+x) * 5 + d] == 2 && (val & d)))
  578. valid = false;
  579. if (val & d) {
  580. /*
  581. * Count up the dead-end statistics.
  582. */
  583. if (deadends[(y*w+x) * 5 + d] <= area) {
  584. deadendtotal += deadends[(y*w+x) * 5 + d];
  585. } else {
  586. nondeadends[nnondeadends++] = d;
  587. }
  588. /*
  589. * Ensure we aren't linking to any tiles,
  590. * through edges not already known to be
  591. * open, which create a loop.
  592. */
  593. if (edgestate[(y*w+x) * 5 + d] == 0) {
  594. int c, k, x2, y2;
  595. OFFSETWH(x2, y2, x, y, d, w, h);
  596. c = dsf_canonify(equivalence, y2*w+x2);
  597. for (k = 0; k < nequiv; k++)
  598. if (c == equiv[k])
  599. break;
  600. if (k == nequiv)
  601. equiv[nequiv++] = c;
  602. else
  603. valid = false;
  604. }
  605. }
  606. }
  607. if (nnondeadends == 0) {
  608. /*
  609. * If this orientation links together dead-ends
  610. * with a total area of less than the entire
  611. * grid, it is invalid.
  612. *
  613. * (We add 1 to deadendtotal because of the
  614. * tile itself, of course; one tile linking
  615. * dead ends of size 2 and 3 forms a subnetwork
  616. * with a total area of 6, not 5.)
  617. */
  618. if (deadendtotal > 0 && deadendtotal+1 < area)
  619. valid = false;
  620. } else if (nnondeadends == 1) {
  621. /*
  622. * If this orientation links together one or
  623. * more dead-ends with precisely one
  624. * non-dead-end, then we may have to mark that
  625. * non-dead-end as a dead end going the other
  626. * way. However, it depends on whether all
  627. * other orientations share the same property.
  628. */
  629. deadendtotal++;
  630. if (deadendmax[nondeadends[0]] < deadendtotal)
  631. deadendmax[nondeadends[0]] = deadendtotal;
  632. } else {
  633. /*
  634. * If this orientation links together two or
  635. * more non-dead-ends, then we can rule out the
  636. * possibility of putting in new dead-end
  637. * markings in those directions.
  638. */
  639. int k;
  640. for (k = 0; k < nnondeadends; k++)
  641. deadendmax[nondeadends[k]] = area+1;
  642. }
  643. if (valid)
  644. tilestate[(y*w+x) * 4 + j++] = val;
  645. #ifdef SOLVER_DIAGNOSTICS
  646. else
  647. printf("ruling out orientation %x at %d,%d\n", val, x, y);
  648. #endif
  649. }
  650. if (j == 0) {
  651. /* If we've ruled out all possible orientations for a
  652. * tile, then our puzzle has no solution at all. */
  653. return -1;
  654. }
  655. if (j < i) {
  656. done_something = true;
  657. /*
  658. * We have ruled out at least one tile orientation.
  659. * Make sure the rest are blanked.
  660. */
  661. while (j < 4)
  662. tilestate[(y*w+x) * 4 + j++] = 255;
  663. }
  664. /*
  665. * Now go through the tile orientations again and see
  666. * if we've deduced anything new about any edges.
  667. */
  668. {
  669. int a, o;
  670. a = 0xF; o = 0;
  671. for (i = 0; i < 4 && tilestate[(y*w+x) * 4 + i] != 255; i++) {
  672. a &= tilestate[(y*w+x) * 4 + i];
  673. o |= tilestate[(y*w+x) * 4 + i];
  674. }
  675. for (d = 1; d <= 8; d += d)
  676. if (edgestate[(y*w+x) * 5 + d] == 0) {
  677. int x2, y2, d2;
  678. OFFSETWH(x2, y2, x, y, d, w, h);
  679. d2 = F(d);
  680. if (a & d) {
  681. /* This edge is open in all orientations. */
  682. #ifdef SOLVER_DIAGNOSTICS
  683. printf("marking edge %d,%d:%d open\n", x, y, d);
  684. #endif
  685. edgestate[(y*w+x) * 5 + d] = 1;
  686. edgestate[(y2*w+x2) * 5 + d2] = 1;
  687. dsf_merge(equivalence, y*w+x, y2*w+x2);
  688. done_something = true;
  689. todo_add(todo, y2*w+x2);
  690. } else if (!(o & d)) {
  691. /* This edge is closed in all orientations. */
  692. #ifdef SOLVER_DIAGNOSTICS
  693. printf("marking edge %d,%d:%d closed\n", x, y, d);
  694. #endif
  695. edgestate[(y*w+x) * 5 + d] = 2;
  696. edgestate[(y2*w+x2) * 5 + d2] = 2;
  697. done_something = true;
  698. todo_add(todo, y2*w+x2);
  699. }
  700. }
  701. }
  702. /*
  703. * Now check the dead-end markers and see if any of
  704. * them has lowered from the real ones.
  705. */
  706. for (d = 1; d <= 8; d += d) {
  707. int x2, y2, d2;
  708. OFFSETWH(x2, y2, x, y, d, w, h);
  709. d2 = F(d);
  710. if (deadendmax[d] > 0 &&
  711. deadends[(y2*w+x2) * 5 + d2] > deadendmax[d]) {
  712. #ifdef SOLVER_DIAGNOSTICS
  713. printf("setting dead end value %d,%d:%d to %d\n",
  714. x2, y2, d2, deadendmax[d]);
  715. #endif
  716. deadends[(y2*w+x2) * 5 + d2] = deadendmax[d];
  717. done_something = true;
  718. todo_add(todo, y2*w+x2);
  719. }
  720. }
  721. }
  722. }
  723. /*
  724. * Mark all completely determined tiles as locked.
  725. */
  726. j = +1;
  727. for (i = 0; i < w*h; i++) {
  728. if (tilestate[i * 4 + 1] == 255) {
  729. assert(tilestate[i * 4 + 0] != 255);
  730. tiles[i] = tilestate[i * 4] | LOCKED;
  731. } else {
  732. tiles[i] &= ~LOCKED;
  733. j = 0;
  734. }
  735. }
  736. /*
  737. * Free up working space.
  738. */
  739. todo_free(todo);
  740. sfree(tilestate);
  741. sfree(edgestate);
  742. sfree(deadends);
  743. dsf_free(equivalence);
  744. return j;
  745. }
  746. /* ----------------------------------------------------------------------
  747. * Randomly select a new game description.
  748. */
  749. /*
  750. * Function to randomly perturb an ambiguous section in a grid, to
  751. * attempt to ensure unique solvability.
  752. */
  753. static void perturb(int w, int h, unsigned char *tiles, bool wrapping,
  754. random_state *rs, int startx, int starty, int startd)
  755. {
  756. struct xyd *perimeter, *perim2, *loop[2], looppos[2];
  757. int nperim, perimsize, nloop[2], loopsize[2];
  758. int x, y, d, i;
  759. /*
  760. * We know that the tile at (startx,starty) is part of an
  761. * ambiguous section, and we also know that its neighbour in
  762. * direction startd is fully specified. We begin by tracing all
  763. * the way round the ambiguous area.
  764. */
  765. nperim = perimsize = 0;
  766. perimeter = NULL;
  767. x = startx;
  768. y = starty;
  769. d = startd;
  770. #ifdef PERTURB_DIAGNOSTICS
  771. printf("perturb %d,%d:%d\n", x, y, d);
  772. #endif
  773. do {
  774. int x2, y2, d2;
  775. if (nperim >= perimsize) {
  776. perimsize = perimsize * 3 / 2 + 32;
  777. perimeter = sresize(perimeter, perimsize, struct xyd);
  778. }
  779. perimeter[nperim].x = x;
  780. perimeter[nperim].y = y;
  781. perimeter[nperim].direction = d;
  782. nperim++;
  783. #ifdef PERTURB_DIAGNOSTICS
  784. printf("perimeter: %d,%d:%d\n", x, y, d);
  785. #endif
  786. /*
  787. * First, see if we can simply turn left from where we are
  788. * and find another locked square.
  789. */
  790. d2 = A(d);
  791. OFFSETWH(x2, y2, x, y, d2, w, h);
  792. if ((!wrapping && (abs(x2-x) > 1 || abs(y2-y) > 1)) ||
  793. (tiles[y2*w+x2] & LOCKED)) {
  794. d = d2;
  795. } else {
  796. /*
  797. * Failing that, step left into the new square and look
  798. * in front of us.
  799. */
  800. x = x2;
  801. y = y2;
  802. OFFSETWH(x2, y2, x, y, d, w, h);
  803. if ((wrapping || (abs(x2-x) <= 1 && abs(y2-y) <= 1)) &&
  804. !(tiles[y2*w+x2] & LOCKED)) {
  805. /*
  806. * And failing _that_, we're going to have to step
  807. * forward into _that_ square and look right at the
  808. * same locked square as we started with.
  809. */
  810. x = x2;
  811. y = y2;
  812. d = C(d);
  813. }
  814. }
  815. } while (x != startx || y != starty || d != startd);
  816. /*
  817. * Our technique for perturbing this ambiguous area is to
  818. * search round its edge for a join we can make: that is, an
  819. * edge on the perimeter which is (a) not currently connected,
  820. * and (b) connecting it would not yield a full cross on either
  821. * side. Then we make that join, search round the network to
  822. * find the loop thus constructed, and sever the loop at a
  823. * randomly selected other point.
  824. */
  825. perim2 = snewn(nperim, struct xyd);
  826. memcpy(perim2, perimeter, nperim * sizeof(struct xyd));
  827. /* Shuffle the perimeter, so as to search it without directional bias. */
  828. shuffle(perim2, nperim, sizeof(*perim2), rs);
  829. for (i = 0; i < nperim; i++) {
  830. int x2, y2;
  831. x = perim2[i].x;
  832. y = perim2[i].y;
  833. d = perim2[i].direction;
  834. OFFSETWH(x2, y2, x, y, d, w, h);
  835. if (!wrapping && (abs(x2-x) > 1 || abs(y2-y) > 1))
  836. continue; /* can't link across non-wrapping border */
  837. if (tiles[y*w+x] & d)
  838. continue; /* already linked in this direction! */
  839. if (((tiles[y*w+x] | d) & 15) == 15)
  840. continue; /* can't turn this tile into a cross */
  841. if (((tiles[y2*w+x2] | F(d)) & 15) == 15)
  842. continue; /* can't turn other tile into a cross */
  843. /*
  844. * We've found the point at which we're going to make a new
  845. * link.
  846. */
  847. #ifdef PERTURB_DIAGNOSTICS
  848. printf("linking %d,%d:%d\n", x, y, d);
  849. #endif
  850. tiles[y*w+x] |= d;
  851. tiles[y2*w+x2] |= F(d);
  852. break;
  853. }
  854. sfree(perim2);
  855. if (i == nperim) {
  856. sfree(perimeter);
  857. return; /* nothing we can do! */
  858. }
  859. /*
  860. * Now we've constructed a new link, we need to find the entire
  861. * loop of which it is a part.
  862. *
  863. * In principle, this involves doing a complete search round
  864. * the network. However, I anticipate that in the vast majority
  865. * of cases the loop will be quite small, so what I'm going to
  866. * do is make _two_ searches round the network in parallel, one
  867. * keeping its metaphorical hand on the left-hand wall while
  868. * the other keeps its hand on the right. As soon as one of
  869. * them gets back to its starting point, I abandon the other.
  870. */
  871. for (i = 0; i < 2; i++) {
  872. loopsize[i] = nloop[i] = 0;
  873. loop[i] = NULL;
  874. looppos[i].x = x;
  875. looppos[i].y = y;
  876. looppos[i].direction = d;
  877. }
  878. while (1) {
  879. for (i = 0; i < 2; i++) {
  880. int x2, y2, j;
  881. x = looppos[i].x;
  882. y = looppos[i].y;
  883. d = looppos[i].direction;
  884. OFFSETWH(x2, y2, x, y, d, w, h);
  885. /*
  886. * Add this path segment to the loop, unless it exactly
  887. * reverses the previous one on the loop in which case
  888. * we take it away again.
  889. */
  890. #ifdef PERTURB_DIAGNOSTICS
  891. printf("looppos[%d] = %d,%d:%d\n", i, x, y, d);
  892. #endif
  893. if (nloop[i] > 0 &&
  894. loop[i][nloop[i]-1].x == x2 &&
  895. loop[i][nloop[i]-1].y == y2 &&
  896. loop[i][nloop[i]-1].direction == F(d)) {
  897. #ifdef PERTURB_DIAGNOSTICS
  898. printf("removing path segment %d,%d:%d from loop[%d]\n",
  899. x2, y2, F(d), i);
  900. #endif
  901. nloop[i]--;
  902. } else {
  903. if (nloop[i] >= loopsize[i]) {
  904. loopsize[i] = loopsize[i] * 3 / 2 + 32;
  905. loop[i] = sresize(loop[i], loopsize[i], struct xyd);
  906. }
  907. #ifdef PERTURB_DIAGNOSTICS
  908. printf("adding path segment %d,%d:%d to loop[%d]\n",
  909. x, y, d, i);
  910. #endif
  911. loop[i][nloop[i]++] = looppos[i];
  912. }
  913. #ifdef PERTURB_DIAGNOSTICS
  914. printf("tile at new location is %x\n", tiles[y2*w+x2] & 0xF);
  915. #endif
  916. d = F(d);
  917. for (j = 0; j < 4; j++) {
  918. if (i == 0)
  919. d = A(d);
  920. else
  921. d = C(d);
  922. #ifdef PERTURB_DIAGNOSTICS
  923. printf("trying dir %d\n", d);
  924. #endif
  925. if (tiles[y2*w+x2] & d) {
  926. looppos[i].x = x2;
  927. looppos[i].y = y2;
  928. looppos[i].direction = d;
  929. break;
  930. }
  931. }
  932. assert(j < 4);
  933. assert(nloop[i] > 0);
  934. if (looppos[i].x == loop[i][0].x &&
  935. looppos[i].y == loop[i][0].y &&
  936. looppos[i].direction == loop[i][0].direction) {
  937. #ifdef PERTURB_DIAGNOSTICS
  938. printf("loop %d finished tracking\n", i);
  939. #endif
  940. /*
  941. * Having found our loop, we now sever it at a
  942. * randomly chosen point - absolutely any will do -
  943. * which is not the one we joined it at to begin
  944. * with. Conveniently, the one we joined it at is
  945. * loop[i][0], so we just avoid that one.
  946. */
  947. j = random_upto(rs, nloop[i]-1) + 1;
  948. x = loop[i][j].x;
  949. y = loop[i][j].y;
  950. d = loop[i][j].direction;
  951. OFFSETWH(x2, y2, x, y, d, w, h);
  952. tiles[y*w+x] &= ~d;
  953. tiles[y2*w+x2] &= ~F(d);
  954. break;
  955. }
  956. }
  957. if (i < 2)
  958. break;
  959. }
  960. sfree(loop[0]);
  961. sfree(loop[1]);
  962. /*
  963. * Finally, we must mark the entire disputed section as locked,
  964. * to prevent the perturb function being called on it multiple
  965. * times.
  966. *
  967. * To do this, we _sort_ the perimeter of the area. The
  968. * existing xyd_cmp function will arrange things into columns
  969. * for us, in such a way that each column has the edges in
  970. * vertical order. Then we can work down each column and fill
  971. * in all the squares between an up edge and a down edge.
  972. */
  973. qsort(perimeter, nperim, sizeof(struct xyd), xyd_cmp);
  974. x = y = -1;
  975. for (i = 0; i <= nperim; i++) {
  976. if (i == nperim || perimeter[i].x > x) {
  977. /*
  978. * Fill in everything from the last Up edge to the
  979. * bottom of the grid, if necessary.
  980. */
  981. if (x != -1) {
  982. while (y < h) {
  983. #ifdef PERTURB_DIAGNOSTICS
  984. printf("resolved: locking tile %d,%d\n", x, y);
  985. #endif
  986. tiles[y * w + x] |= LOCKED;
  987. y++;
  988. }
  989. x = y = -1;
  990. }
  991. if (i == nperim)
  992. break;
  993. x = perimeter[i].x;
  994. y = 0;
  995. }
  996. if (perimeter[i].direction == U) {
  997. x = perimeter[i].x;
  998. y = perimeter[i].y;
  999. } else if (perimeter[i].direction == D) {
  1000. /*
  1001. * Fill in everything from the last Up edge to here.
  1002. */
  1003. assert(x == perimeter[i].x && y <= perimeter[i].y);
  1004. while (y <= perimeter[i].y) {
  1005. #ifdef PERTURB_DIAGNOSTICS
  1006. printf("resolved: locking tile %d,%d\n", x, y);
  1007. #endif
  1008. tiles[y * w + x] |= LOCKED;
  1009. y++;
  1010. }
  1011. x = y = -1;
  1012. }
  1013. }
  1014. sfree(perimeter);
  1015. }
  1016. static int *compute_loops_inner(int w, int h, bool wrapping,
  1017. const unsigned char *tiles,
  1018. const unsigned char *barriers,
  1019. bool include_unlocked_squares);
  1020. static char *new_game_desc(const game_params *params, random_state *rs,
  1021. char **aux, bool interactive)
  1022. {
  1023. tree234 *possibilities, *barriertree;
  1024. int w, h, x, y, cx, cy, nbarriers;
  1025. unsigned char *tiles, *barriers;
  1026. char *desc, *p;
  1027. w = params->width;
  1028. h = params->height;
  1029. cx = w / 2;
  1030. cy = h / 2;
  1031. tiles = snewn(w * h, unsigned char);
  1032. barriers = snewn(w * h, unsigned char);
  1033. begin_generation:
  1034. memset(tiles, 0, w * h);
  1035. memset(barriers, 0, w * h);
  1036. /*
  1037. * Construct the unshuffled grid.
  1038. *
  1039. * To do this, we simply start at the centre point, repeatedly
  1040. * choose a random possibility out of the available ways to
  1041. * extend a used square into an unused one, and do it. After
  1042. * extending the third line out of a square, we remove the
  1043. * fourth from the possibilities list to avoid any full-cross
  1044. * squares (which would make the game too easy because they
  1045. * only have one orientation).
  1046. *
  1047. * The slightly worrying thing is the avoidance of full-cross
  1048. * squares. Can this cause our unsophisticated construction
  1049. * algorithm to paint itself into a corner, by getting into a
  1050. * situation where there are some unreached squares and the
  1051. * only way to reach any of them is to extend a T-piece into a
  1052. * full cross?
  1053. *
  1054. * Answer: no it can't, and here's a proof.
  1055. *
  1056. * Any contiguous group of such unreachable squares must be
  1057. * surrounded on _all_ sides by T-pieces pointing away from the
  1058. * group. (If not, then there is a square which can be extended
  1059. * into one of the `unreachable' ones, and so it wasn't
  1060. * unreachable after all.) In particular, this implies that
  1061. * each contiguous group of unreachable squares must be
  1062. * rectangular in shape (any deviation from that yields a
  1063. * non-T-piece next to an `unreachable' square).
  1064. *
  1065. * So we have a rectangle of unreachable squares, with T-pieces
  1066. * forming a solid border around the rectangle. The corners of
  1067. * that border must be connected (since every tile connects all
  1068. * the lines arriving in it), and therefore the border must
  1069. * form a closed loop around the rectangle.
  1070. *
  1071. * But this can't have happened in the first place, since we
  1072. * _know_ we've avoided creating closed loops! Hence, no such
  1073. * situation can ever arise, and the naive grid construction
  1074. * algorithm will guaranteeably result in a complete grid
  1075. * containing no unreached squares, no full crosses _and_ no
  1076. * closed loops. []
  1077. */
  1078. possibilities = newtree234(xyd_cmp_nc);
  1079. if (cx+1 < w)
  1080. add234(possibilities, new_xyd(cx, cy, R));
  1081. if (cy-1 >= 0)
  1082. add234(possibilities, new_xyd(cx, cy, U));
  1083. if (cx-1 >= 0)
  1084. add234(possibilities, new_xyd(cx, cy, L));
  1085. if (cy+1 < h)
  1086. add234(possibilities, new_xyd(cx, cy, D));
  1087. while (count234(possibilities) > 0) {
  1088. int i;
  1089. struct xyd *xyd;
  1090. int x1, y1, d1, x2, y2, d2, d;
  1091. /*
  1092. * Extract a randomly chosen possibility from the list.
  1093. */
  1094. i = random_upto(rs, count234(possibilities));
  1095. xyd = delpos234(possibilities, i);
  1096. x1 = xyd->x;
  1097. y1 = xyd->y;
  1098. d1 = xyd->direction;
  1099. sfree(xyd);
  1100. OFFSET(x2, y2, x1, y1, d1, params);
  1101. d2 = F(d1);
  1102. #ifdef GENERATION_DIAGNOSTICS
  1103. printf("picked (%d,%d,%c) <-> (%d,%d,%c)\n",
  1104. x1, y1, "0RU3L567D9abcdef"[d1], x2, y2, "0RU3L567D9abcdef"[d2]);
  1105. #endif
  1106. /*
  1107. * Make the connection. (We should be moving to an as yet
  1108. * unused tile.)
  1109. */
  1110. index(params, tiles, x1, y1) |= d1;
  1111. assert(index(params, tiles, x2, y2) == 0);
  1112. index(params, tiles, x2, y2) |= d2;
  1113. /*
  1114. * If we have created a T-piece, remove its last
  1115. * possibility.
  1116. */
  1117. if (COUNT(index(params, tiles, x1, y1)) == 3) {
  1118. struct xyd xyd1, *xydp;
  1119. xyd1.x = x1;
  1120. xyd1.y = y1;
  1121. xyd1.direction = 0x0F ^ index(params, tiles, x1, y1);
  1122. xydp = find234(possibilities, &xyd1, NULL);
  1123. if (xydp) {
  1124. #ifdef GENERATION_DIAGNOSTICS
  1125. printf("T-piece; removing (%d,%d,%c)\n",
  1126. xydp->x, xydp->y, "0RU3L567D9abcdef"[xydp->direction]);
  1127. #endif
  1128. del234(possibilities, xydp);
  1129. sfree(xydp);
  1130. }
  1131. }
  1132. /*
  1133. * Remove all other possibilities that were pointing at the
  1134. * tile we've just moved into.
  1135. */
  1136. for (d = 1; d < 0x10; d <<= 1) {
  1137. int x3, y3, d3;
  1138. struct xyd xyd1, *xydp;
  1139. OFFSET(x3, y3, x2, y2, d, params);
  1140. d3 = F(d);
  1141. xyd1.x = x3;
  1142. xyd1.y = y3;
  1143. xyd1.direction = d3;
  1144. xydp = find234(possibilities, &xyd1, NULL);
  1145. if (xydp) {
  1146. #ifdef GENERATION_DIAGNOSTICS
  1147. printf("Loop avoidance; removing (%d,%d,%c)\n",
  1148. xydp->x, xydp->y, "0RU3L567D9abcdef"[xydp->direction]);
  1149. #endif
  1150. del234(possibilities, xydp);
  1151. sfree(xydp);
  1152. }
  1153. }
  1154. /*
  1155. * Add new possibilities to the list for moving _out_ of
  1156. * the tile we have just moved into.
  1157. */
  1158. for (d = 1; d < 0x10; d <<= 1) {
  1159. int x3, y3;
  1160. if (d == d2)
  1161. continue; /* we've got this one already */
  1162. if (!params->wrapping) {
  1163. if (d == U && y2 == 0)
  1164. continue;
  1165. if (d == D && y2 == h-1)
  1166. continue;
  1167. if (d == L && x2 == 0)
  1168. continue;
  1169. if (d == R && x2 == w-1)
  1170. continue;
  1171. }
  1172. OFFSET(x3, y3, x2, y2, d, params);
  1173. if (index(params, tiles, x3, y3))
  1174. continue; /* this would create a loop */
  1175. #ifdef GENERATION_DIAGNOSTICS
  1176. printf("New frontier; adding (%d,%d,%c)\n",
  1177. x2, y2, "0RU3L567D9abcdef"[d]);
  1178. #endif
  1179. add234(possibilities, new_xyd(x2, y2, d));
  1180. }
  1181. }
  1182. /* Having done that, we should have no possibilities remaining. */
  1183. assert(count234(possibilities) == 0);
  1184. freetree234(possibilities);
  1185. if (params->unique) {
  1186. int prevn = -1;
  1187. /*
  1188. * Run the solver to check unique solubility.
  1189. */
  1190. while (net_solver(w, h, tiles, NULL, params->wrapping) != 1) {
  1191. int n = 0;
  1192. /*
  1193. * We expect (in most cases) that most of the grid will
  1194. * be uniquely specified already, and the remaining
  1195. * ambiguous sections will be small and separate. So
  1196. * our strategy is to find each individual such
  1197. * section, and perform a perturbation on the network
  1198. * in that area.
  1199. */
  1200. for (y = 0; y < h; y++) for (x = 0; x < w; x++) {
  1201. if (x+1 < w && ((tiles[y*w+x] ^ tiles[y*w+x+1]) & LOCKED)) {
  1202. n++;
  1203. if (tiles[y*w+x] & LOCKED)
  1204. perturb(w, h, tiles, params->wrapping, rs, x+1, y, L);
  1205. else
  1206. perturb(w, h, tiles, params->wrapping, rs, x, y, R);
  1207. }
  1208. if (y+1 < h && ((tiles[y*w+x] ^ tiles[(y+1)*w+x]) & LOCKED)) {
  1209. n++;
  1210. if (tiles[y*w+x] & LOCKED)
  1211. perturb(w, h, tiles, params->wrapping, rs, x, y+1, U);
  1212. else
  1213. perturb(w, h, tiles, params->wrapping, rs, x, y, D);
  1214. }
  1215. }
  1216. /*
  1217. * Now n counts the number of ambiguous sections we
  1218. * have fiddled with. If we haven't managed to decrease
  1219. * it from the last time we ran the solver, give up and
  1220. * regenerate the entire grid.
  1221. */
  1222. if (prevn != -1 && prevn <= n)
  1223. goto begin_generation; /* (sorry) */
  1224. prevn = n;
  1225. }
  1226. /*
  1227. * The solver will have left a lot of LOCKED bits lying
  1228. * around in the tiles array. Remove them.
  1229. */
  1230. for (x = 0; x < w*h; x++)
  1231. tiles[x] &= ~LOCKED;
  1232. }
  1233. /*
  1234. * Now compute a list of the possible barrier locations.
  1235. */
  1236. barriertree = newtree234(xyd_cmp_nc);
  1237. for (y = 0; y < h; y++) {
  1238. for (x = 0; x < w; x++) {
  1239. if (!(index(params, tiles, x, y) & R) &&
  1240. (params->wrapping || x < w-1))
  1241. add234(barriertree, new_xyd(x, y, R));
  1242. if (!(index(params, tiles, x, y) & D) &&
  1243. (params->wrapping || y < h-1))
  1244. add234(barriertree, new_xyd(x, y, D));
  1245. }
  1246. }
  1247. /*
  1248. * Save the unshuffled grid in aux.
  1249. */
  1250. {
  1251. char *solution;
  1252. int i;
  1253. solution = snewn(w * h + 1, char);
  1254. for (i = 0; i < w * h; i++)
  1255. solution[i] = "0123456789abcdef"[tiles[i] & 0xF];
  1256. solution[w*h] = '\0';
  1257. *aux = solution;
  1258. }
  1259. /*
  1260. * Now shuffle the grid.
  1261. *
  1262. * In order to avoid accidentally generating an already-solved
  1263. * grid, we will reshuffle as necessary to ensure that at least
  1264. * one edge has a mismatched connection.
  1265. *
  1266. * This can always be done, since validate_params() enforces a
  1267. * grid area of at least 2 and our generator never creates
  1268. * either type of rotationally invariant tile (cross and
  1269. * blank). Hence there must be at least one edge separating
  1270. * distinct tiles, and it must be possible to find orientations
  1271. * of those tiles such that one tile is trying to connect
  1272. * through that edge and the other is not.
  1273. *
  1274. * (We could be more subtle, and allow the shuffle to generate
  1275. * a grid in which all tiles match up locally and the only
  1276. * criterion preventing the grid from being already solved is
  1277. * connectedness. However, that would take more effort, and
  1278. * it's easier to simply make sure every grid is _obviously_
  1279. * not solved.)
  1280. *
  1281. * We also require that our shuffle produces no loops in the
  1282. * initial grid state, because it's a bit rude to light up a 'HEY,
  1283. * YOU DID SOMETHING WRONG!' indicator when the user hasn't even
  1284. * had a chance to do _anything_ yet. This also is possible just
  1285. * by retrying the whole shuffle on failure, because it's clear
  1286. * that at least one non-solved shuffle with no loops must exist.
  1287. * (Proof: take the _solved_ state of the puzzle, and rotate one
  1288. * endpoint.)
  1289. */
  1290. while (1) {
  1291. int mismatches, prev_loopsquares, this_loopsquares, i;
  1292. int *loops;
  1293. shuffle:
  1294. for (y = 0; y < h; y++) {
  1295. for (x = 0; x < w; x++) {
  1296. int orig = index(params, tiles, x, y);
  1297. int rot = random_upto(rs, 4);
  1298. index(params, tiles, x, y) = ROT(orig, rot);
  1299. }
  1300. }
  1301. /*
  1302. * Check for loops, and try to fix them by reshuffling just
  1303. * the squares involved.
  1304. */
  1305. prev_loopsquares = w*h+1;
  1306. while (1) {
  1307. loops = compute_loops_inner(w, h, params->wrapping, tiles, NULL,
  1308. true);
  1309. this_loopsquares = 0;
  1310. for (i = 0; i < w*h; i++) {
  1311. if (loops[i]) {
  1312. int orig = tiles[i];
  1313. int rot = random_upto(rs, 4);
  1314. tiles[i] = ROT(orig, rot);
  1315. this_loopsquares++;
  1316. }
  1317. }
  1318. sfree(loops);
  1319. if (this_loopsquares > prev_loopsquares) {
  1320. /*
  1321. * We're increasing rather than reducing the number of
  1322. * loops. Give up and go back to the full shuffle.
  1323. */
  1324. goto shuffle;
  1325. }
  1326. if (this_loopsquares == 0)
  1327. break;
  1328. prev_loopsquares = this_loopsquares;
  1329. }
  1330. mismatches = 0;
  1331. /*
  1332. * I can't even be bothered to check for mismatches across
  1333. * a wrapping edge, so I'm just going to enforce that there
  1334. * must be a mismatch across a non-wrapping edge, which is
  1335. * still always possible.
  1336. */
  1337. for (y = 0; y < h; y++) for (x = 0; x < w; x++) {
  1338. if (x+1 < w && ((ROT(index(params, tiles, x, y), 2) ^
  1339. index(params, tiles, x+1, y)) & L))
  1340. mismatches++;
  1341. if (y+1 < h && ((ROT(index(params, tiles, x, y), 2) ^
  1342. index(params, tiles, x, y+1)) & U))
  1343. mismatches++;
  1344. }
  1345. if (mismatches == 0)
  1346. continue;
  1347. /* OK. */
  1348. break;
  1349. }
  1350. /*
  1351. * And now choose barrier locations. (We carefully do this
  1352. * _after_ shuffling, so that changing the barrier rate in the
  1353. * params while keeping the random seed the same will give the
  1354. * same shuffled grid and _only_ change the barrier locations.
  1355. * Also the way we choose barrier locations, by repeatedly
  1356. * choosing one possibility from the list until we have enough,
  1357. * is designed to ensure that raising the barrier rate while
  1358. * keeping the seed the same will provide a superset of the
  1359. * previous barrier set - i.e. if you ask for 10 barriers, and
  1360. * then decide that's still too hard and ask for 20, you'll get
  1361. * the original 10 plus 10 more, rather than getting 20 new
  1362. * ones and the chance of remembering your first 10.)
  1363. */
  1364. nbarriers = (int)(params->barrier_probability * count234(barriertree));
  1365. assert(nbarriers >= 0 && nbarriers <= count234(barriertree));
  1366. while (nbarriers > 0) {
  1367. int i;
  1368. struct xyd *xyd;
  1369. int x1, y1, d1, x2, y2, d2;
  1370. /*
  1371. * Extract a randomly chosen barrier from the list.
  1372. */
  1373. i = random_upto(rs, count234(barriertree));
  1374. xyd = delpos234(barriertree, i);
  1375. assert(xyd != NULL);
  1376. x1 = xyd->x;
  1377. y1 = xyd->y;
  1378. d1 = xyd->direction;
  1379. sfree(xyd);
  1380. OFFSET(x2, y2, x1, y1, d1, params);
  1381. d2 = F(d1);
  1382. index(params, barriers, x1, y1) |= d1;
  1383. index(params, barriers, x2, y2) |= d2;
  1384. nbarriers--;
  1385. }
  1386. /*
  1387. * Clean up the rest of the barrier list.
  1388. */
  1389. {
  1390. struct xyd *xyd;
  1391. while ( (xyd = delpos234(barriertree, 0)) != NULL)
  1392. sfree(xyd);
  1393. freetree234(barriertree);
  1394. }
  1395. /*
  1396. * Finally, encode the grid into a string game description.
  1397. *
  1398. * My syntax is extremely simple: each square is encoded as a
  1399. * hex digit in which bit 0 means a connection on the right,
  1400. * bit 1 means up, bit 2 left and bit 3 down. (i.e. the same
  1401. * encoding as used internally). Each digit is followed by
  1402. * optional barrier indicators: `v' means a vertical barrier to
  1403. * the right of it, and `h' means a horizontal barrier below
  1404. * it.
  1405. */
  1406. desc = snewn(w * h * 3 + 1, char);
  1407. p = desc;
  1408. for (y = 0; y < h; y++) {
  1409. for (x = 0; x < w; x++) {
  1410. *p++ = "0123456789abcdef"[index(params, tiles, x, y)];
  1411. if ((params->wrapping || x < w-1) &&
  1412. (index(params, barriers, x, y) & R))
  1413. *p++ = 'v';
  1414. if ((params->wrapping || y < h-1) &&
  1415. (index(params, barriers, x, y) & D))
  1416. *p++ = 'h';
  1417. }
  1418. }
  1419. assert(p - desc <= w*h*3);
  1420. *p = '\0';
  1421. sfree(tiles);
  1422. sfree(barriers);
  1423. return desc;
  1424. }
  1425. static const char *validate_desc(const game_params *params, const char *desc)
  1426. {
  1427. int w = params->width, h = params->height;
  1428. int i;
  1429. for (i = 0; i < w*h; i++) {
  1430. if (*desc >= '0' && *desc <= '9')
  1431. /* OK */;
  1432. else if (*desc >= 'a' && *desc <= 'f')
  1433. /* OK */;
  1434. else if (*desc >= 'A' && *desc <= 'F')
  1435. /* OK */;
  1436. else if (!*desc)
  1437. return "Game description shorter than expected";
  1438. else
  1439. return "Game description contained unexpected character";
  1440. desc++;
  1441. while (*desc == 'h' || *desc == 'v')
  1442. desc++;
  1443. }
  1444. if (*desc)
  1445. return "Game description longer than expected";
  1446. return NULL;
  1447. }
  1448. /* ----------------------------------------------------------------------
  1449. * Construct an initial game state, given a description and parameters.
  1450. */
  1451. static game_state *new_game(midend *me, const game_params *params,
  1452. const char *desc)
  1453. {
  1454. game_state *state;
  1455. int w, h, x, y;
  1456. assert(params->width > 0 && params->height > 0);
  1457. assert(params->width > 1 || params->height > 1);
  1458. /*
  1459. * Create a blank game state.
  1460. */
  1461. state = snew(game_state);
  1462. w = state->width = params->width;
  1463. h = state->height = params->height;
  1464. state->wrapping = params->wrapping;
  1465. state->imm = snew(game_immutable_state);
  1466. state->imm->refcount = 1;
  1467. state->last_rotate_dir = state->last_rotate_x = state->last_rotate_y = 0;
  1468. state->completed = state->used_solve = false;
  1469. state->tiles = snewn(state->width * state->height, unsigned char);
  1470. memset(state->tiles, 0, state->width * state->height);
  1471. state->imm->barriers = snewn(state->width * state->height, unsigned char);
  1472. memset(state->imm->barriers, 0, state->width * state->height);
  1473. /*
  1474. * Parse the game description into the grid.
  1475. */
  1476. for (y = 0; y < h; y++) {
  1477. for (x = 0; x < w; x++) {
  1478. if (*desc >= '0' && *desc <= '9')
  1479. tile(state, x, y) = *desc - '0';
  1480. else if (*desc >= 'a' && *desc <= 'f')
  1481. tile(state, x, y) = *desc - 'a' + 10;
  1482. else if (*desc >= 'A' && *desc <= 'F')
  1483. tile(state, x, y) = *desc - 'A' + 10;
  1484. if (*desc)
  1485. desc++;
  1486. while (*desc == 'h' || *desc == 'v') {
  1487. int x2, y2, d1, d2;
  1488. if (*desc == 'v')
  1489. d1 = R;
  1490. else
  1491. d1 = D;
  1492. OFFSET(x2, y2, x, y, d1, state);
  1493. d2 = F(d1);
  1494. barrier(state, x, y) |= d1;
  1495. barrier(state, x2, y2) |= d2;
  1496. desc++;
  1497. }
  1498. }
  1499. }
  1500. /*
  1501. * Set up border barriers if this is a non-wrapping game.
  1502. */
  1503. if (!state->wrapping) {
  1504. for (x = 0; x < state->width; x++) {
  1505. barrier(state, x, 0) |= U;
  1506. barrier(state, x, state->height-1) |= D;
  1507. }
  1508. for (y = 0; y < state->height; y++) {
  1509. barrier(state, 0, y) |= L;
  1510. barrier(state, state->width-1, y) |= R;
  1511. }
  1512. } else {
  1513. /*
  1514. * We check whether this is de-facto a non-wrapping game
  1515. * despite the parameters, in case we were passed the
  1516. * description of a non-wrapping game. This is so that we
  1517. * can change some aspects of the UI behaviour.
  1518. */
  1519. state->wrapping = false;
  1520. for (x = 0; x < state->width; x++)
  1521. if (!(barrier(state, x, 0) & U) ||
  1522. !(barrier(state, x, state->height-1) & D))
  1523. state->wrapping = true;
  1524. for (y = 0; y < state->height; y++)
  1525. if (!(barrier(state, 0, y) & L) ||
  1526. !(barrier(state, state->width-1, y) & R))
  1527. state->wrapping = true;
  1528. }
  1529. return state;
  1530. }
  1531. static game_state *dup_game(const game_state *state)
  1532. {
  1533. game_state *ret;
  1534. ret = snew(game_state);
  1535. ret->imm = state->imm;
  1536. ret->imm->refcount++;
  1537. ret->width = state->width;
  1538. ret->height = state->height;
  1539. ret->wrapping = state->wrapping;
  1540. ret->completed = state->completed;
  1541. ret->used_solve = state->used_solve;
  1542. ret->last_rotate_dir = state->last_rotate_dir;
  1543. ret->last_rotate_x = state->last_rotate_x;
  1544. ret->last_rotate_y = state->last_rotate_y;
  1545. ret->tiles = snewn(state->width * state->height, unsigned char);
  1546. memcpy(ret->tiles, state->tiles, state->width * state->height);
  1547. return ret;
  1548. }
  1549. static void free_game(game_state *state)
  1550. {
  1551. if (--state->imm->refcount == 0) {
  1552. sfree(state->imm->barriers);
  1553. sfree(state->imm);
  1554. }
  1555. sfree(state->tiles);
  1556. sfree(state);
  1557. }
  1558. static char *solve_game(const game_state *state, const game_state *currstate,
  1559. const char *aux, const char **error)
  1560. {
  1561. unsigned char *tiles;
  1562. char *ret;
  1563. int retlen, retsize;
  1564. int i;
  1565. tiles = snewn(state->width * state->height, unsigned char);
  1566. if (!aux) {
  1567. /*
  1568. * Run the internal solver on the provided grid. This might
  1569. * not yield a complete solution.
  1570. */
  1571. int solver_result;
  1572. memcpy(tiles, state->tiles, state->width * state->height);
  1573. solver_result = net_solver(state->width, state->height, tiles,
  1574. state->imm->barriers, state->wrapping);
  1575. if (solver_result < 0) {
  1576. *error = "No solution exists for this puzzle";
  1577. sfree(tiles);
  1578. return NULL;
  1579. }
  1580. } else {
  1581. for (i = 0; i < state->width * state->height; i++) {
  1582. int c = aux[i];
  1583. if (c >= '0' && c <= '9')
  1584. tiles[i] = c - '0';
  1585. else if (c >= 'a' && c <= 'f')
  1586. tiles[i] = c - 'a' + 10;
  1587. else if (c >= 'A' && c <= 'F')
  1588. tiles[i] = c - 'A' + 10;
  1589. tiles[i] |= LOCKED;
  1590. }
  1591. }
  1592. /*
  1593. * Now construct a string which can be passed to execute_move()
  1594. * to transform the current grid into the solved one.
  1595. */
  1596. retsize = 256;
  1597. ret = snewn(retsize, char);
  1598. retlen = 0;
  1599. ret[retlen++] = 'S';
  1600. for (i = 0; i < state->width * state->height; i++) {
  1601. int from = currstate->tiles[i], to = tiles[i];
  1602. int ft = from & (R|L|U|D), tt = to & (R|L|U|D);
  1603. int x = i % state->width, y = i / state->width;
  1604. int chr = '\0';
  1605. char buf[80], *p = buf;
  1606. if (from == to)
  1607. continue; /* nothing needs doing at all */
  1608. /*
  1609. * To transform this tile into the desired tile: first
  1610. * unlock the tile if it's locked, then rotate it if
  1611. * necessary, then lock it if necessary.
  1612. */
  1613. if (from & LOCKED)
  1614. p += sprintf(p, ";L%d,%d", x, y);
  1615. if (tt == A(ft))
  1616. chr = 'A';
  1617. else if (tt == C(ft))
  1618. chr = 'C';
  1619. else if (tt == F(ft))
  1620. chr = 'F';
  1621. else {
  1622. assert(tt == ft);
  1623. chr = '\0';
  1624. }
  1625. if (chr)
  1626. p += sprintf(p, ";%c%d,%d", chr, x, y);
  1627. if (to & LOCKED)
  1628. p += sprintf(p, ";L%d,%d", x, y);
  1629. if (p > buf) {
  1630. if (retlen + (p - buf) >= retsize) {
  1631. retsize = retlen + (p - buf) + 512;
  1632. ret = sresize(ret, retsize, char);
  1633. }
  1634. memcpy(ret+retlen, buf, p - buf);
  1635. retlen += p - buf;
  1636. }
  1637. }
  1638. assert(retlen < retsize);
  1639. ret[retlen] = '\0';
  1640. ret = sresize(ret, retlen+1, char);
  1641. sfree(tiles);
  1642. return ret;
  1643. }
  1644. /* ----------------------------------------------------------------------
  1645. * Utility routine.
  1646. */
  1647. /*
  1648. * Compute which squares are reachable from the centre square, as a
  1649. * quick visual aid to determining how close the game is to
  1650. * completion. This is also a simple way to tell if the game _is_
  1651. * completed - just call this function and see whether every square
  1652. * is marked active.
  1653. */
  1654. static unsigned char *compute_active(const game_state *state, int cx, int cy)
  1655. {
  1656. unsigned char *active;
  1657. tree234 *todo;
  1658. struct xyd *xyd;
  1659. active = snewn(state->width * state->height, unsigned char);
  1660. memset(active, 0, state->width * state->height);
  1661. assert(0 <= cx && cx < state->width);
  1662. assert(0 <= cy && cy < state->height);
  1663. /*
  1664. * We only store (x,y) pairs in todo, but it's easier to reuse
  1665. * xyd_cmp and just store direction 0 every time.
  1666. */
  1667. todo = newtree234(xyd_cmp_nc);
  1668. index(state, active, cx, cy) = ACTIVE;
  1669. add234(todo, new_xyd(cx, cy, 0));
  1670. while ( (xyd = delpos234(todo, 0)) != NULL) {
  1671. int x1, y1, d1, x2, y2, d2;
  1672. x1 = xyd->x;
  1673. y1 = xyd->y;
  1674. sfree(xyd);
  1675. for (d1 = 1; d1 < 0x10; d1 <<= 1) {
  1676. OFFSET(x2, y2, x1, y1, d1, state);
  1677. d2 = F(d1);
  1678. /*
  1679. * If the next tile in this direction is connected to
  1680. * us, and there isn't a barrier in the way, and it
  1681. * isn't already marked active, then mark it active and
  1682. * add it to the to-examine list.
  1683. */
  1684. if ((tile(state, x1, y1) & d1) &&
  1685. (tile(state, x2, y2) & d2) &&
  1686. !(barrier(state, x1, y1) & d1) &&
  1687. !index(state, active, x2, y2)) {
  1688. index(state, active, x2, y2) = ACTIVE;
  1689. add234(todo, new_xyd(x2, y2, 0));
  1690. }
  1691. }
  1692. }
  1693. /* Now we expect the todo list to have shrunk to zero size. */
  1694. assert(count234(todo) == 0);
  1695. freetree234(todo);
  1696. return active;
  1697. }
  1698. struct net_neighbour_ctx {
  1699. int w, h;
  1700. const unsigned char *tiles, *barriers;
  1701. int i, n, neighbours[4];
  1702. bool include_unlocked_squares;
  1703. };
  1704. static int net_neighbour(int vertex, void *vctx)
  1705. {
  1706. struct net_neighbour_ctx *ctx = (struct net_neighbour_ctx *)vctx;
  1707. if (vertex >= 0) {
  1708. int x = vertex % ctx->w, y = vertex / ctx->w;
  1709. int tile, dir, x1, y1, v1;
  1710. ctx->i = ctx->n = 0;
  1711. tile = ctx->tiles[vertex];
  1712. if (ctx->barriers)
  1713. tile &= ~ctx->barriers[vertex];
  1714. for (dir = 1; dir < 0x10; dir <<= 1) {
  1715. if (!(tile & dir))
  1716. continue;
  1717. OFFSETWH(x1, y1, x, y, dir, ctx->w, ctx->h);
  1718. v1 = y1 * ctx->w + x1;
  1719. if (!ctx->include_unlocked_squares &&
  1720. !(tile & ctx->tiles[v1] & LOCKED))
  1721. continue;
  1722. if (ctx->tiles[v1] & F(dir))
  1723. ctx->neighbours[ctx->n++] = v1;
  1724. }
  1725. }
  1726. if (ctx->i < ctx->n)
  1727. return ctx->neighbours[ctx->i++];
  1728. else
  1729. return -1;
  1730. }
  1731. static int *compute_loops_inner(int w, int h, bool wrapping,
  1732. const unsigned char *tiles,
  1733. const unsigned char *barriers,
  1734. bool include_unlocked_squares)
  1735. {
  1736. struct net_neighbour_ctx ctx;
  1737. struct findloopstate *fls;
  1738. int *loops;
  1739. int x, y, v;
  1740. fls = findloop_new_state(w*h);
  1741. ctx.w = w;
  1742. ctx.h = h;
  1743. ctx.tiles = tiles;
  1744. ctx.barriers = barriers;
  1745. ctx.include_unlocked_squares = include_unlocked_squares;
  1746. findloop_run(fls, w*h, net_neighbour, &ctx);
  1747. loops = snewn(w*h, int);
  1748. for (y = 0; y < h; y++) {
  1749. for (x = 0; x < w; x++) {
  1750. int x1, y1, v1, dir;
  1751. int flags = 0;
  1752. v = y * w + x;
  1753. for (dir = 1; dir < 0x10; dir <<= 1) {
  1754. if ((tiles[v] & dir) &&
  1755. !(barriers && (barriers[y*w+x] & dir))) {
  1756. OFFSETWH(x1, y1, x, y, dir, w, h);
  1757. v1 = y1 * w + x1;
  1758. if (!include_unlocked_squares &&
  1759. !(tiles[v] & tiles[v1] & LOCKED))
  1760. continue;
  1761. if ((tiles[v1] & F(dir)) &&
  1762. findloop_is_loop_edge(fls, y*w+x, y1*w+x1))
  1763. flags |= ERR(dir);
  1764. }
  1765. }
  1766. loops[y*w+x] = flags;
  1767. }
  1768. }
  1769. findloop_free_state(fls);
  1770. return loops;
  1771. }
  1772. static int *compute_loops(const game_state *state,
  1773. bool include_unlocked_squares)
  1774. {
  1775. return compute_loops_inner(state->width, state->height, state->wrapping,
  1776. state->tiles, state->imm->barriers,
  1777. include_unlocked_squares);
  1778. }
  1779. struct game_ui {
  1780. int org_x, org_y; /* origin */
  1781. int cx, cy; /* source tile (game coordinates) */
  1782. int cur_x, cur_y;
  1783. bool cur_visible;
  1784. random_state *rs; /* used for jumbling */
  1785. #ifdef USE_DRAGGING
  1786. int dragtilex, dragtiley, dragstartx, dragstarty;
  1787. bool dragged;
  1788. #endif
  1789. bool unlocked_loops;
  1790. };
  1791. static game_ui *new_ui(const game_state *state)
  1792. {
  1793. void *seed;
  1794. int seedsize;
  1795. game_ui *ui = snew(game_ui);
  1796. ui->unlocked_loops = true;
  1797. if (state) {
  1798. ui->org_x = ui->org_y = 0;
  1799. ui->cur_x = ui->cx = state->width / 2;
  1800. ui->cur_y = ui->cy = state->height / 2;
  1801. ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false);
  1802. get_random_seed(&seed, &seedsize);
  1803. ui->rs = random_new(seed, seedsize);
  1804. sfree(seed);
  1805. } else {
  1806. ui->rs = NULL;
  1807. }
  1808. return ui;
  1809. }
  1810. static void free_ui(game_ui *ui)
  1811. {
  1812. if (ui->rs)
  1813. random_free(ui->rs);
  1814. sfree(ui);
  1815. }
  1816. static char *encode_ui(const game_ui *ui)
  1817. {
  1818. char buf[120];
  1819. /*
  1820. * We preserve the origin and centre-point coordinates over a
  1821. * serialise.
  1822. */
  1823. sprintf(buf, "O%d,%d;C%d,%d", ui->org_x, ui->org_y, ui->cx, ui->cy);
  1824. return dupstr(buf);
  1825. }
  1826. static void decode_ui(game_ui *ui, const char *encoding,
  1827. const game_state *state)
  1828. {
  1829. int org_x, org_y, cx, cy;
  1830. if (sscanf(encoding, "O%d,%d;C%d,%d", &org_x, &org_y, &cx, &cy) == 4) {
  1831. if (0 <= org_x && org_x < state->width &&
  1832. 0 <= org_y && org_y < state->height) {
  1833. ui->org_x = org_x;
  1834. ui->org_y = org_y;
  1835. }
  1836. if (0 <= cx && cx < state->width &&
  1837. 0 <= cy && cy < state->height) {
  1838. ui->cx = cx;
  1839. ui->cy = cy;
  1840. }
  1841. }
  1842. }
  1843. static config_item *get_prefs(game_ui *ui)
  1844. {
  1845. config_item *ret;
  1846. ret = snewn(2, config_item);
  1847. ret[0].name = "Highlight loops involving unlocked squares";
  1848. ret[0].kw = "unlocked-loops";
  1849. ret[0].type = C_BOOLEAN;
  1850. ret[0].u.boolean.bval = ui->unlocked_loops;
  1851. ret[1].name = NULL;
  1852. ret[1].type = C_END;
  1853. return ret;
  1854. }
  1855. static void set_prefs(game_ui *ui, const config_item *cfg)
  1856. {
  1857. ui->unlocked_loops = cfg[0].u.boolean.bval;
  1858. }
  1859. static void game_changed_state(game_ui *ui, const game_state *oldstate,
  1860. const game_state *newstate)
  1861. {
  1862. }
  1863. static const char *current_key_label(const game_ui *ui,
  1864. const game_state *state, int button)
  1865. {
  1866. if (tile(state, ui->cur_x, ui->cur_y) & LOCKED) {
  1867. if (button == CURSOR_SELECT2) return "Unlock";
  1868. } else {
  1869. if (button == CURSOR_SELECT) return "Rotate";
  1870. if (button == CURSOR_SELECT2) return "Lock";
  1871. }
  1872. return "";
  1873. }
  1874. struct game_drawstate {
  1875. int width, height;
  1876. int tilesize;
  1877. unsigned long *visible, *to_draw;
  1878. };
  1879. /* ----------------------------------------------------------------------
  1880. * Process a move.
  1881. */
  1882. static char *interpret_move(const game_state *state, game_ui *ui,
  1883. const game_drawstate *ds,
  1884. int x, int y, int button)
  1885. {
  1886. char *nullret;
  1887. int tx = -1, ty = -1, dir = 0;
  1888. bool shift = button & MOD_SHFT, ctrl = button & MOD_CTRL;
  1889. enum {
  1890. NONE, ROTATE_LEFT, ROTATE_180, ROTATE_RIGHT, TOGGLE_LOCK, JUMBLE,
  1891. MOVE_ORIGIN, MOVE_SOURCE, MOVE_ORIGIN_AND_SOURCE, MOVE_CURSOR
  1892. } action;
  1893. button &= ~MOD_MASK;
  1894. nullret = NULL;
  1895. action = NONE;
  1896. if (button == LEFT_BUTTON ||
  1897. button == MIDDLE_BUTTON ||
  1898. #ifdef USE_DRAGGING
  1899. button == LEFT_DRAG ||
  1900. button == LEFT_RELEASE ||
  1901. button == RIGHT_DRAG ||
  1902. button == RIGHT_RELEASE ||
  1903. #endif
  1904. button == RIGHT_BUTTON) {
  1905. if (ui->cur_visible) {
  1906. ui->cur_visible = false;
  1907. nullret = MOVE_UI_UPDATE;
  1908. }
  1909. /*
  1910. * The button must have been clicked on a valid tile.
  1911. */
  1912. x -= WINDOW_OFFSET + LINE_THICK;
  1913. y -= WINDOW_OFFSET + LINE_THICK;
  1914. if (x < 0 || y < 0)
  1915. return nullret;
  1916. tx = x / TILE_SIZE;
  1917. ty = y / TILE_SIZE;
  1918. if (tx >= state->width || ty >= state->height)
  1919. return nullret;
  1920. /* Transform from physical to game coords */
  1921. tx = (tx + ui->org_x) % state->width;
  1922. ty = (ty + ui->org_y) % state->height;
  1923. if (x % TILE_SIZE >= TILE_SIZE - LINE_THICK ||
  1924. y % TILE_SIZE >= TILE_SIZE - LINE_THICK)
  1925. return nullret;
  1926. #ifdef USE_DRAGGING
  1927. if (button == MIDDLE_BUTTON
  1928. #ifdef STYLUS_BASED
  1929. || button == RIGHT_BUTTON /* with a stylus, `right-click' locks */
  1930. #endif
  1931. ) {
  1932. /*
  1933. * Middle button never drags: it only toggles the lock.
  1934. */
  1935. action = TOGGLE_LOCK;
  1936. } else if (button == LEFT_BUTTON
  1937. #ifndef STYLUS_BASED
  1938. || button == RIGHT_BUTTON /* (see above) */
  1939. #endif
  1940. ) {
  1941. /*
  1942. * Otherwise, we note down the start point for a drag.
  1943. */
  1944. ui->dragtilex = tx;
  1945. ui->dragtiley = ty;
  1946. ui->dragstartx = x % TILE_SIZE;
  1947. ui->dragstarty = y % TILE_SIZE;
  1948. ui->dragged = false;
  1949. return nullret; /* no actual action */
  1950. } else if (button == LEFT_DRAG
  1951. #ifndef STYLUS_BASED
  1952. || button == RIGHT_DRAG
  1953. #endif
  1954. ) {
  1955. /*
  1956. * Find the new drag point and see if it necessitates a
  1957. * rotation.
  1958. */
  1959. int x0,y0, xA,yA, xC,yC, xF,yF;
  1960. int mx, my;
  1961. int d0, dA, dC, dF, dmin;
  1962. tx = ui->dragtilex;
  1963. ty = ui->dragtiley;
  1964. mx = x - (ui->dragtilex * TILE_SIZE);
  1965. my = y - (ui->dragtiley * TILE_SIZE);
  1966. x0 = ui->dragstartx;
  1967. y0 = ui->dragstarty;
  1968. xA = ui->dragstarty;
  1969. yA = TILE_SIZE-1 - ui->dragstartx;
  1970. xF = TILE_SIZE-1 - ui->dragstartx;
  1971. yF = TILE_SIZE-1 - ui->dragstarty;
  1972. xC = TILE_SIZE-1 - ui->dragstarty;
  1973. yC = ui->dragstartx;
  1974. d0 = (mx-x0)*(mx-x0) + (my-y0)*(my-y0);
  1975. dA = (mx-xA)*(mx-xA) + (my-yA)*(my-yA);
  1976. dF = (mx-xF)*(mx-xF) + (my-yF)*(my-yF);
  1977. dC = (mx-xC)*(mx-xC) + (my-yC)*(my-yC);
  1978. dmin = min(min(d0,dA),min(dF,dC));
  1979. if (d0 == dmin) {
  1980. return nullret;
  1981. } else if (dF == dmin) {
  1982. action = ROTATE_180;
  1983. ui->dragstartx = xF;
  1984. ui->dragstarty = yF;
  1985. ui->dragged = true;
  1986. } else if (dA == dmin) {
  1987. action = ROTATE_LEFT;
  1988. ui->dragstartx = xA;
  1989. ui->dragstarty = yA;
  1990. ui->dragged = true;
  1991. } else /* dC == dmin */ {
  1992. action = ROTATE_RIGHT;
  1993. ui->dragstartx = xC;
  1994. ui->dragstarty = yC;
  1995. ui->dragged = true;
  1996. }
  1997. } else if (button == LEFT_RELEASE
  1998. #ifndef STYLUS_BASED
  1999. || button == RIGHT_RELEASE
  2000. #endif
  2001. ) {
  2002. if (!ui->dragged) {
  2003. /*
  2004. * There was a click but no perceptible drag:
  2005. * revert to single-click behaviour.
  2006. */
  2007. tx = ui->dragtilex;
  2008. ty = ui->dragtiley;
  2009. if (button == LEFT_RELEASE)
  2010. action = ROTATE_LEFT;
  2011. else
  2012. action = ROTATE_RIGHT;
  2013. } else
  2014. return nullret; /* no action */
  2015. }
  2016. #else /* USE_DRAGGING */
  2017. action = (button == LEFT_BUTTON ? ROTATE_LEFT :
  2018. button == RIGHT_BUTTON ? ROTATE_RIGHT : TOGGLE_LOCK);
  2019. #endif /* USE_DRAGGING */
  2020. } else if (IS_CURSOR_MOVE(button)) {
  2021. switch (button) {
  2022. case CURSOR_UP: dir = U; break;
  2023. case CURSOR_DOWN: dir = D; break;
  2024. case CURSOR_LEFT: dir = L; break;
  2025. case CURSOR_RIGHT: dir = R; break;
  2026. default: return nullret;
  2027. }
  2028. if (shift && ctrl) action = MOVE_ORIGIN_AND_SOURCE;
  2029. else if (shift) action = MOVE_ORIGIN;
  2030. else if (ctrl) action = MOVE_SOURCE;
  2031. else action = MOVE_CURSOR;
  2032. } else if (button == 'a' || button == 's' || button == 'd' ||
  2033. button == 'A' || button == 'S' || button == 'D' ||
  2034. button == 'f' || button == 'F' ||
  2035. IS_CURSOR_SELECT(button)) {
  2036. tx = ui->cur_x;
  2037. ty = ui->cur_y;
  2038. if (button == 'a' || button == 'A' || button == CURSOR_SELECT)
  2039. action = ROTATE_LEFT;
  2040. else if (button == 's' || button == 'S' || button == CURSOR_SELECT2)
  2041. action = TOGGLE_LOCK;
  2042. else if (button == 'd' || button == 'D')
  2043. action = ROTATE_RIGHT;
  2044. else if (button == 'f' || button == 'F')
  2045. action = ROTATE_180;
  2046. ui->cur_visible = true;
  2047. } else if (button == 'j' || button == 'J') {
  2048. /* XXX should we have some mouse control for this? */
  2049. action = JUMBLE;
  2050. } else
  2051. return nullret;
  2052. /*
  2053. * The middle button locks or unlocks a tile. (A locked tile
  2054. * cannot be turned, and is visually marked as being locked.
  2055. * This is a convenience for the player, so that once they are
  2056. * sure which way round a tile goes, they can lock it and thus
  2057. * avoid forgetting later on that they'd already done that one;
  2058. * and the locking also prevents them turning the tile by
  2059. * accident. If they change their mind, another middle click
  2060. * unlocks it.)
  2061. */
  2062. if (action == TOGGLE_LOCK) {
  2063. char buf[80];
  2064. sprintf(buf, "L%d,%d", tx, ty);
  2065. return dupstr(buf);
  2066. } else if (action == ROTATE_LEFT || action == ROTATE_RIGHT ||
  2067. action == ROTATE_180) {
  2068. char buf[80];
  2069. /*
  2070. * The left and right buttons have no effect if clicked on a
  2071. * locked tile.
  2072. */
  2073. if (tile(state, tx, ty) & LOCKED)
  2074. return nullret;
  2075. /*
  2076. * Otherwise, turn the tile one way or the other. Left button
  2077. * turns anticlockwise; right button turns clockwise.
  2078. */
  2079. sprintf(buf, "%c%d,%d", (int)(action == ROTATE_LEFT ? 'A' :
  2080. action == ROTATE_RIGHT ? 'C' : 'F'), tx, ty);
  2081. return dupstr(buf);
  2082. } else if (action == JUMBLE) {
  2083. /*
  2084. * Jumble all unlocked tiles to random orientations.
  2085. */
  2086. int jx, jy, maxlen;
  2087. char *ret, *p;
  2088. /*
  2089. * Maximum string length assumes no int can be converted to
  2090. * decimal and take more than 11 digits!
  2091. */
  2092. maxlen = state->width * state->height * 25 + 3;
  2093. ret = snewn(maxlen, char);
  2094. p = ret;
  2095. *p++ = 'J';
  2096. for (jy = 0; jy < state->height; jy++) {
  2097. for (jx = 0; jx < state->width; jx++) {
  2098. if (!(tile(state, jx, jy) & LOCKED)) {
  2099. int rot = random_upto(ui->rs, 4);
  2100. if (rot) {
  2101. p += sprintf(p, ";%c%d,%d", "AFC"[rot-1], jx, jy);
  2102. }
  2103. }
  2104. }
  2105. }
  2106. *p++ = '\0';
  2107. assert(p - ret < maxlen);
  2108. ret = sresize(ret, p - ret, char);
  2109. return ret;
  2110. } else if (action == MOVE_ORIGIN || action == MOVE_SOURCE ||
  2111. action == MOVE_ORIGIN_AND_SOURCE || action == MOVE_CURSOR) {
  2112. assert(dir != 0);
  2113. if (action == MOVE_ORIGIN || action == MOVE_ORIGIN_AND_SOURCE) {
  2114. if (state->wrapping) {
  2115. OFFSET(ui->org_x, ui->org_y, ui->org_x, ui->org_y, dir, state);
  2116. } else return nullret; /* disallowed for non-wrapping grids */
  2117. }
  2118. if (action == MOVE_SOURCE || action == MOVE_ORIGIN_AND_SOURCE) {
  2119. OFFSET(ui->cx, ui->cy, ui->cx, ui->cy, dir, state);
  2120. }
  2121. if (action == MOVE_CURSOR) {
  2122. OFFSET(ui->cur_x, ui->cur_y, ui->cur_x, ui->cur_y, dir, state);
  2123. ui->cur_visible = true;
  2124. }
  2125. return MOVE_UI_UPDATE;
  2126. } else {
  2127. return NULL;
  2128. }
  2129. }
  2130. static game_state *execute_move(const game_state *from, const char *move)
  2131. {
  2132. game_state *ret;
  2133. int tx = -1, ty = -1, n, orig;
  2134. bool noanim;
  2135. ret = dup_game(from);
  2136. if (move[0] == 'J' || move[0] == 'S') {
  2137. if (move[0] == 'S')
  2138. ret->used_solve = true;
  2139. move++;
  2140. if (*move == ';')
  2141. move++;
  2142. noanim = true;
  2143. } else
  2144. noanim = false;
  2145. ret->last_rotate_dir = 0; /* suppress animation */
  2146. ret->last_rotate_x = ret->last_rotate_y = 0;
  2147. while (*move) {
  2148. if ((move[0] == 'A' || move[0] == 'C' ||
  2149. move[0] == 'F' || move[0] == 'L') &&
  2150. sscanf(move+1, "%d,%d%n", &tx, &ty, &n) >= 2 &&
  2151. tx >= 0 && tx < from->width && ty >= 0 && ty < from->height) {
  2152. orig = tile(ret, tx, ty);
  2153. if (move[0] == 'A') {
  2154. tile(ret, tx, ty) = A(orig);
  2155. if (!noanim)
  2156. ret->last_rotate_dir = +1;
  2157. } else if (move[0] == 'F') {
  2158. tile(ret, tx, ty) = F(orig);
  2159. if (!noanim)
  2160. ret->last_rotate_dir = +2; /* + for sake of argument */
  2161. } else if (move[0] == 'C') {
  2162. tile(ret, tx, ty) = C(orig);
  2163. if (!noanim)
  2164. ret->last_rotate_dir = -1;
  2165. } else {
  2166. assert(move[0] == 'L');
  2167. tile(ret, tx, ty) ^= LOCKED;
  2168. }
  2169. move += 1 + n;
  2170. if (*move == ';') move++;
  2171. } else {
  2172. free_game(ret);
  2173. return NULL;
  2174. }
  2175. }
  2176. if (!noanim) {
  2177. if (tx == -1 || ty == -1) { free_game(ret); return NULL; }
  2178. ret->last_rotate_x = tx;
  2179. ret->last_rotate_y = ty;
  2180. }
  2181. /*
  2182. * Check whether the game has been completed.
  2183. *
  2184. * For this purpose it doesn't matter where the source square is,
  2185. * because we can start from anywhere (or, at least, any square
  2186. * that's non-empty!), and correctly determine whether the game is
  2187. * completed.
  2188. */
  2189. {
  2190. unsigned char *active;
  2191. int pos;
  2192. bool complete = true;
  2193. for (pos = 0; pos < ret->width * ret->height; pos++)
  2194. if (ret->tiles[pos] & 0xF)
  2195. break;
  2196. if (pos < ret->width * ret->height) {
  2197. active = compute_active(ret, pos % ret->width, pos / ret->width);
  2198. for (pos = 0; pos < ret->width * ret->height; pos++)
  2199. if ((ret->tiles[pos] & 0xF) && !active[pos]) {
  2200. complete = false;
  2201. break;
  2202. }
  2203. sfree(active);
  2204. }
  2205. if (complete)
  2206. ret->completed = true;
  2207. }
  2208. return ret;
  2209. }
  2210. /* ----------------------------------------------------------------------
  2211. * Routines for drawing the game position on the screen.
  2212. */
  2213. static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
  2214. {
  2215. game_drawstate *ds = snew(game_drawstate);
  2216. int i, ncells;
  2217. ds->width = state->width;
  2218. ds->height = state->height;
  2219. ncells = (state->width+2) * (state->height+2);
  2220. ds->visible = snewn(ncells, unsigned long);
  2221. ds->to_draw = snewn(ncells, unsigned long);
  2222. ds->tilesize = 0; /* undecided yet */
  2223. for (i = 0; i < ncells; i++)
  2224. ds->visible[i] = -1;
  2225. return ds;
  2226. }
  2227. #define dsindex(ds, field, x, y) ((ds)->field[((y)+1)*((ds)->width+2)+((x)+1)])
  2228. #define visible(ds, x, y) dsindex(ds, visible, x, y)
  2229. #define todraw(ds, x, y) dsindex(ds, to_draw, x, y)
  2230. static void game_free_drawstate(drawing *dr, game_drawstate *ds)
  2231. {
  2232. sfree(ds->visible);
  2233. sfree(ds->to_draw);
  2234. sfree(ds);
  2235. }
  2236. static void game_compute_size(const game_params *params, int tilesize,
  2237. const game_ui *ui, int *x, int *y)
  2238. {
  2239. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  2240. struct { int tilesize; } ads, *ds = &ads;
  2241. ads.tilesize = tilesize;
  2242. *x = WINDOW_OFFSET * 2 + TILE_SIZE * params->width + LINE_THICK;
  2243. *y = WINDOW_OFFSET * 2 + TILE_SIZE * params->height + LINE_THICK;
  2244. }
  2245. static void game_set_size(drawing *dr, game_drawstate *ds,
  2246. const game_params *params, int tilesize)
  2247. {
  2248. ds->tilesize = tilesize;
  2249. }
  2250. static float *game_colours(frontend *fe, int *ncolours)
  2251. {
  2252. float *ret;
  2253. ret = snewn(NCOLOURS * 3, float);
  2254. *ncolours = NCOLOURS;
  2255. /*
  2256. * Basic background colour is whatever the front end thinks is
  2257. * a sensible default.
  2258. */
  2259. frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
  2260. /*
  2261. * Wires are black.
  2262. */
  2263. ret[COL_WIRE * 3 + 0] = 0.0F;
  2264. ret[COL_WIRE * 3 + 1] = 0.0F;
  2265. ret[COL_WIRE * 3 + 2] = 0.0F;
  2266. /*
  2267. * Powered wires and powered endpoints are cyan.
  2268. */
  2269. ret[COL_POWERED * 3 + 0] = 0.0F;
  2270. ret[COL_POWERED * 3 + 1] = 1.0F;
  2271. ret[COL_POWERED * 3 + 2] = 1.0F;
  2272. /*
  2273. * Barriers are red.
  2274. */
  2275. ret[COL_BARRIER * 3 + 0] = 1.0F;
  2276. ret[COL_BARRIER * 3 + 1] = 0.0F;
  2277. ret[COL_BARRIER * 3 + 2] = 0.0F;
  2278. /*
  2279. * Highlighted errors are red as well.
  2280. */
  2281. ret[COL_ERR * 3 + 0] = 1.0F;
  2282. ret[COL_ERR * 3 + 1] = 0.0F;
  2283. ret[COL_ERR * 3 + 2] = 0.0F;
  2284. /*
  2285. * Unpowered endpoints are blue.
  2286. */
  2287. ret[COL_ENDPOINT * 3 + 0] = 0.0F;
  2288. ret[COL_ENDPOINT * 3 + 1] = 0.0F;
  2289. ret[COL_ENDPOINT * 3 + 2] = 1.0F;
  2290. /*
  2291. * Tile borders are a darker grey than the background.
  2292. */
  2293. ret[COL_BORDER * 3 + 0] = 0.5F * ret[COL_BACKGROUND * 3 + 0];
  2294. ret[COL_BORDER * 3 + 1] = 0.5F * ret[COL_BACKGROUND * 3 + 1];
  2295. ret[COL_BORDER * 3 + 2] = 0.5F * ret[COL_BACKGROUND * 3 + 2];
  2296. /*
  2297. * Locked tiles are a grey in between those two.
  2298. */
  2299. ret[COL_LOCKED * 3 + 0] = 0.75F * ret[COL_BACKGROUND * 3 + 0];
  2300. ret[COL_LOCKED * 3 + 1] = 0.75F * ret[COL_BACKGROUND * 3 + 1];
  2301. ret[COL_LOCKED * 3 + 2] = 0.75F * ret[COL_BACKGROUND * 3 + 2];
  2302. return ret;
  2303. }
  2304. static void rotated_coords(float *ox, float *oy, const float matrix[4],
  2305. float cx, float cy, float ix, float iy)
  2306. {
  2307. *ox = matrix[0] * ix + matrix[2] * iy + cx;
  2308. *oy = matrix[1] * ix + matrix[3] * iy + cy;
  2309. }
  2310. /* Flags describing the visible features of a tile. */
  2311. #define TILE_BARRIER_SHIFT 0 /* 4 bits: R U L D */
  2312. #define TILE_BARRIER_CORNER_SHIFT 4 /* 4 bits: RU UL LD DR */
  2313. #define TILE_KEYBOARD_CURSOR (1<<8) /* 1 bit if cursor is here */
  2314. #define TILE_WIRE_SHIFT 9 /* 8 bits: RR UU LL DD
  2315. * Each pair: 0=no wire, 1=unpowered,
  2316. * 2=powered, 3=error highlight */
  2317. #define TILE_ENDPOINT_SHIFT 17 /* 2 bits: 0=no endpoint, 1=unpowered,
  2318. * 2=powered, 3=power-source square */
  2319. #define TILE_WIRE_ON_EDGE_SHIFT 19 /* 8 bits: RR UU LL DD,
  2320. * same encoding as TILE_WIRE_SHIFT */
  2321. #define TILE_ROTATING (1UL<<27) /* 1 bit if tile is rotating */
  2322. #define TILE_LOCKED (1UL<<28) /* 1 bit if tile is locked */
  2323. static void draw_wires(drawing *dr, int cx, int cy, int radius,
  2324. unsigned long tile, int bitmap,
  2325. int colour, int halfwidth, const float matrix[4])
  2326. {
  2327. float fpoints[12*2];
  2328. int points[12*2];
  2329. int npoints, d, dsh, i;
  2330. bool any_wire_this_colour = false;
  2331. float xf, yf;
  2332. npoints = 0;
  2333. for (d = 1, dsh = 0; d < 16; d *= 2, dsh++) {
  2334. int wiretype = (tile >> (TILE_WIRE_SHIFT + 2*dsh)) & 3;
  2335. fpoints[2*npoints+0] = halfwidth * (X(d) + X(C(d)));
  2336. fpoints[2*npoints+1] = halfwidth * (Y(d) + Y(C(d)));
  2337. npoints++;
  2338. if (bitmap & (1 << wiretype)) {
  2339. fpoints[2*npoints+0] = radius * X(d) + halfwidth * X(C(d));
  2340. fpoints[2*npoints+1] = radius * Y(d) + halfwidth * Y(C(d));
  2341. npoints++;
  2342. fpoints[2*npoints+0] = radius * X(d) + halfwidth * X(A(d));
  2343. fpoints[2*npoints+1] = radius * Y(d) + halfwidth * Y(A(d));
  2344. npoints++;
  2345. any_wire_this_colour = true;
  2346. }
  2347. }
  2348. if (!any_wire_this_colour)
  2349. return;
  2350. for (i = 0; i < npoints; i++) {
  2351. rotated_coords(&xf, &yf, matrix, cx, cy, fpoints[2*i], fpoints[2*i+1]);
  2352. points[2*i] = 0.5F + xf;
  2353. points[2*i+1] = 0.5F + yf;
  2354. }
  2355. draw_polygon(dr, points, npoints, colour, colour);
  2356. }
  2357. static void draw_tile(drawing *dr, game_drawstate *ds, int x, int y,
  2358. unsigned long tile, float angle)
  2359. {
  2360. int tx, ty;
  2361. int clipx, clipy, clipX, clipY, clipw, cliph;
  2362. int border_br = LINE_THICK/2, border_tl = LINE_THICK - border_br;
  2363. int barrier_outline_thick = (LINE_THICK+1)/2;
  2364. int bg, d, dsh, pass;
  2365. int cx, cy, radius;
  2366. float matrix[4];
  2367. tx = WINDOW_OFFSET + TILE_SIZE * x + border_br;
  2368. ty = WINDOW_OFFSET + TILE_SIZE * y + border_br;
  2369. /*
  2370. * Clip to the tile boundary, with adjustments if we're drawing
  2371. * just outside the grid.
  2372. */
  2373. clipx = tx; clipX = tx + TILE_SIZE;
  2374. clipy = ty; clipY = ty + TILE_SIZE;
  2375. if (x == -1) {
  2376. clipx = clipX - border_br - barrier_outline_thick;
  2377. } else if (x == ds->width) {
  2378. clipX = clipx + border_tl + barrier_outline_thick;
  2379. }
  2380. if (y == -1) {
  2381. clipy = clipY - border_br - barrier_outline_thick;
  2382. } else if (y == ds->height) {
  2383. clipY = clipy + border_tl + barrier_outline_thick;
  2384. }
  2385. clipw = clipX - clipx;
  2386. cliph = clipY - clipy;
  2387. clip(dr, clipx, clipy, clipw, cliph);
  2388. /*
  2389. * Clear the clip region.
  2390. */
  2391. bg = (tile & TILE_LOCKED) ? COL_LOCKED : COL_BACKGROUND;
  2392. draw_rect(dr, clipx, clipy, clipw, cliph, bg);
  2393. /*
  2394. * Draw the grid lines.
  2395. */
  2396. {
  2397. int gridl = (x == -1 ? tx+TILE_SIZE-border_br : tx);
  2398. int gridr = (x == ds->width ? tx+border_tl : tx+TILE_SIZE);
  2399. int gridu = (y == -1 ? ty+TILE_SIZE-border_br : ty);
  2400. int gridd = (y == ds->height ? ty+border_tl : ty+TILE_SIZE);
  2401. if (x >= 0)
  2402. draw_rect(dr, tx, gridu, border_tl, gridd-gridu, COL_BORDER);
  2403. if (y >= 0)
  2404. draw_rect(dr, gridl, ty, gridr-gridl, border_tl, COL_BORDER);
  2405. if (x < ds->width)
  2406. draw_rect(dr, tx+TILE_SIZE-border_br, gridu,
  2407. border_br, gridd-gridu, COL_BORDER);
  2408. if (y < ds->height)
  2409. draw_rect(dr, gridl, ty+TILE_SIZE-border_br,
  2410. gridr-gridl, border_br, COL_BORDER);
  2411. }
  2412. /*
  2413. * Draw the keyboard cursor.
  2414. */
  2415. if (tile & TILE_KEYBOARD_CURSOR) {
  2416. int cursorcol = (tile & TILE_LOCKED) ? COL_BACKGROUND : COL_LOCKED;
  2417. int inset_outer = TILE_SIZE/8, inset_inner = inset_outer + LINE_THICK;
  2418. draw_rect(dr, tx + inset_outer, ty + inset_outer,
  2419. TILE_SIZE - 2*inset_outer, TILE_SIZE - 2*inset_outer,
  2420. cursorcol);
  2421. draw_rect(dr, tx + inset_inner, ty + inset_inner,
  2422. TILE_SIZE - 2*inset_inner, TILE_SIZE - 2*inset_inner,
  2423. bg);
  2424. }
  2425. radius = (TILE_SIZE+1)/2;
  2426. cx = tx + radius;
  2427. cy = ty + radius;
  2428. radius++;
  2429. /*
  2430. * Draw protrusions into this cell's edges of wires in
  2431. * neighbouring cells, as given by the TILE_WIRE_ON_EDGE_SHIFT
  2432. * flags. We only draw each of these if there _isn't_ a wire of
  2433. * our own that's going to overlap it, which means either the
  2434. * corresponding TILE_WIRE_SHIFT flag is zero, or else the
  2435. * TILE_ROTATING flag is set (so that our main wire won't be drawn
  2436. * in quite that place anyway).
  2437. */
  2438. for (d = 1, dsh = 0; d < 16; d *= 2, dsh++) {
  2439. int edgetype = ((tile >> (TILE_WIRE_ON_EDGE_SHIFT + 2*dsh)) & 3);
  2440. if (edgetype == 0)
  2441. continue; /* there isn't a wire on the edge */
  2442. if (!(tile & TILE_ROTATING) &&
  2443. ((tile >> (TILE_WIRE_SHIFT + 2*dsh)) & 3) != 0)
  2444. continue; /* wire on edge would be overdrawn anyway */
  2445. for (pass = 0; pass < 2; pass++) {
  2446. int x, y, w, h;
  2447. int col = (pass == 0 || edgetype == 1 ? COL_WIRE :
  2448. edgetype == 2 ? COL_POWERED : COL_ERR);
  2449. int halfwidth = pass == 0 ? 2*LINE_THICK-1 : LINE_THICK-1;
  2450. if (X(d) < 0) {
  2451. x = tx;
  2452. w = border_tl;
  2453. } else if (X(d) > 0) {
  2454. x = tx + TILE_SIZE - border_br;
  2455. w = border_br;
  2456. } else {
  2457. x = cx - halfwidth;
  2458. w = 2 * halfwidth + 1;
  2459. }
  2460. if (Y(d) < 0) {
  2461. y = ty;
  2462. h = border_tl;
  2463. } else if (Y(d) > 0) {
  2464. y = ty + TILE_SIZE - border_br;
  2465. h = border_br;
  2466. } else {
  2467. y = cy - halfwidth;
  2468. h = 2 * halfwidth + 1;
  2469. }
  2470. draw_rect(dr, x, y, w, h, col);
  2471. }
  2472. }
  2473. /*
  2474. * Set up the rotation matrix for the main cell contents, i.e.
  2475. * everything that is centred in the grid square and optionally
  2476. * rotated by an arbitrary angle about that centre point.
  2477. */
  2478. if (tile & TILE_ROTATING) {
  2479. matrix[0] = (float)cos(angle * (float)PI / 180.0F);
  2480. matrix[2] = (float)sin(angle * (float)PI / 180.0F);
  2481. } else {
  2482. matrix[0] = 1.0F;
  2483. matrix[2] = 0.0F;
  2484. }
  2485. matrix[3] = matrix[0];
  2486. matrix[1] = -matrix[2];
  2487. /*
  2488. * Draw the wires.
  2489. */
  2490. draw_wires(dr, cx, cy, radius, tile,
  2491. 0xE, COL_WIRE, 2*LINE_THICK-1, matrix);
  2492. draw_wires(dr, cx, cy, radius, tile,
  2493. 0x4, COL_POWERED, LINE_THICK-1, matrix);
  2494. draw_wires(dr, cx, cy, radius, tile,
  2495. 0x8, COL_ERR, LINE_THICK-1, matrix);
  2496. /*
  2497. * Draw the central box.
  2498. */
  2499. for (pass = 0; pass < 2; pass++) {
  2500. int endtype = (tile >> TILE_ENDPOINT_SHIFT) & 3;
  2501. if (endtype) {
  2502. int i, points[8], col;
  2503. float boxr = TILE_SIZE * 0.24F + (pass == 0 ? LINE_THICK-1 : 0);
  2504. col = (pass == 0 || endtype == 3 ? COL_WIRE :
  2505. endtype == 2 ? COL_POWERED : COL_ENDPOINT);
  2506. points[0] = +1; points[1] = +1;
  2507. points[2] = +1; points[3] = -1;
  2508. points[4] = -1; points[5] = -1;
  2509. points[6] = -1; points[7] = +1;
  2510. for (i = 0; i < 8; i += 2) {
  2511. float x, y;
  2512. rotated_coords(&x, &y, matrix, cx, cy,
  2513. boxr * points[i], boxr * points[i+1]);
  2514. points[i] = x + 0.5F;
  2515. points[i+1] = y + 0.5F;
  2516. }
  2517. draw_polygon(dr, points, 4, col, COL_WIRE);
  2518. }
  2519. }
  2520. /*
  2521. * Draw barriers along grid edges.
  2522. */
  2523. for (pass = 0; pass < 2; pass++) {
  2524. int btl = border_tl, bbr = border_br, col = COL_BARRIER;
  2525. if (pass == 0) {
  2526. btl += barrier_outline_thick;
  2527. bbr += barrier_outline_thick;
  2528. col = COL_WIRE;
  2529. }
  2530. if (tile & (L << TILE_BARRIER_SHIFT))
  2531. draw_rect(dr, tx, ty, btl, TILE_SIZE, col);
  2532. if (tile & (R << TILE_BARRIER_SHIFT))
  2533. draw_rect(dr, tx+TILE_SIZE-bbr, ty, bbr, TILE_SIZE, col);
  2534. if (tile & (U << TILE_BARRIER_SHIFT))
  2535. draw_rect(dr, tx, ty, TILE_SIZE, btl, col);
  2536. if (tile & (D << TILE_BARRIER_SHIFT))
  2537. draw_rect(dr, tx, ty+TILE_SIZE-bbr, TILE_SIZE, bbr, col);
  2538. if (tile & (R << TILE_BARRIER_CORNER_SHIFT))
  2539. draw_rect(dr, tx+TILE_SIZE-bbr, ty, bbr, btl, col);
  2540. if (tile & (U << TILE_BARRIER_CORNER_SHIFT))
  2541. draw_rect(dr, tx, ty, btl, btl, col);
  2542. if (tile & (L << TILE_BARRIER_CORNER_SHIFT))
  2543. draw_rect(dr, tx, ty+TILE_SIZE-bbr, btl, bbr, col);
  2544. if (tile & (D << TILE_BARRIER_CORNER_SHIFT))
  2545. draw_rect(dr, tx+TILE_SIZE-bbr, ty+TILE_SIZE-bbr, bbr, bbr, col);
  2546. }
  2547. /*
  2548. * Unclip and draw update, to finish.
  2549. */
  2550. unclip(dr);
  2551. draw_update(dr, clipx, clipy, clipw, cliph);
  2552. }
  2553. static void game_redraw(drawing *dr, game_drawstate *ds,
  2554. const game_state *oldstate, const game_state *state,
  2555. int dir, const game_ui *ui,
  2556. float t, float ft)
  2557. {
  2558. int tx, ty, dx, dy, d, dsh, last_rotate_dir, frame;
  2559. unsigned char *active;
  2560. int *loops;
  2561. float angle = 0.0;
  2562. tx = ty = -1;
  2563. last_rotate_dir = dir==-1 ? oldstate->last_rotate_dir :
  2564. state->last_rotate_dir;
  2565. if (oldstate && (t < ROTATE_TIME) && last_rotate_dir) {
  2566. /*
  2567. * We're animating a single tile rotation. Find the turning
  2568. * tile.
  2569. */
  2570. tx = (dir==-1 ? oldstate->last_rotate_x : state->last_rotate_x);
  2571. ty = (dir==-1 ? oldstate->last_rotate_y : state->last_rotate_y);
  2572. angle = last_rotate_dir * dir * 90.0F * (t / ROTATE_TIME);
  2573. state = oldstate;
  2574. }
  2575. if (ft > 0) {
  2576. /*
  2577. * We're animating a completion flash. Find which frame
  2578. * we're at.
  2579. */
  2580. frame = (int)(ft / FLASH_FRAME);
  2581. } else {
  2582. frame = 0;
  2583. }
  2584. /*
  2585. * Build up a map of what we want every tile to look like. We
  2586. * include tiles one square outside the grid, for the outer edges
  2587. * of barriers.
  2588. */
  2589. active = compute_active(state, ui->cx, ui->cy);
  2590. loops = compute_loops(state, ui->unlocked_loops);
  2591. for (dy = -1; dy < ds->height+1; dy++) {
  2592. for (dx = -1; dx < ds->width+1; dx++) {
  2593. todraw(ds, dx, dy) = 0;
  2594. }
  2595. }
  2596. for (dy = 0; dy < ds->height; dy++) {
  2597. int gy = (dy + ui->org_y) % ds->height;
  2598. for (dx = 0; dx < ds->width; dx++) {
  2599. int gx = (dx + ui->org_x) % ds->width;
  2600. int t = (tile(state, gx, gy) |
  2601. index(state, loops, gx, gy) |
  2602. index(state, active, gx, gy));
  2603. for (d = 1, dsh = 0; d < 16; d *= 2, dsh++) {
  2604. if (barrier(state, gx, gy) & d) {
  2605. todraw(ds, dx, dy) |=
  2606. d << TILE_BARRIER_SHIFT;
  2607. todraw(ds, dx + X(d), dy + Y(d)) |=
  2608. F(d) << TILE_BARRIER_SHIFT;
  2609. todraw(ds, dx + X(A(d)), dy + Y(A(d))) |=
  2610. C(d) << TILE_BARRIER_CORNER_SHIFT;
  2611. todraw(ds, dx + X(A(d)) + X(d), dy + Y(A(d)) + Y(d)) |=
  2612. F(d) << TILE_BARRIER_CORNER_SHIFT;
  2613. todraw(ds, dx + X(C(d)), dy + Y(C(d))) |=
  2614. d << TILE_BARRIER_CORNER_SHIFT;
  2615. todraw(ds, dx + X(C(d)) + X(d), dy + Y(C(d)) + Y(d)) |=
  2616. A(d) << TILE_BARRIER_CORNER_SHIFT;
  2617. }
  2618. if (t & d) {
  2619. int edgeval;
  2620. /* Highlight as an error any edge in a locked tile that
  2621. * is adjacent to a lack-of-edge in another locked tile,
  2622. * or to a barrier */
  2623. if (t & LOCKED) {
  2624. if (barrier(state, gx, gy) & d) {
  2625. t |= ERR(d);
  2626. } else {
  2627. int ox, oy, t2;
  2628. OFFSET(ox, oy, gx, gy, d, state);
  2629. t2 = tile(state, ox, oy);
  2630. if ((t2 & LOCKED) && !(t2 & F(d))) {
  2631. t |= ERR(d);
  2632. }
  2633. }
  2634. }
  2635. edgeval = (t & ERR(d) ? 3 : t & ACTIVE ? 2 : 1);
  2636. todraw(ds, dx, dy) |= edgeval << (TILE_WIRE_SHIFT + dsh*2);
  2637. if (!(gx == tx && gy == ty)) {
  2638. todraw(ds, dx + X(d), dy + Y(d)) |=
  2639. edgeval << (TILE_WIRE_ON_EDGE_SHIFT + (dsh ^ 2)*2);
  2640. }
  2641. }
  2642. }
  2643. if (ui->cur_visible && gx == ui->cur_x && gy == ui->cur_y)
  2644. todraw(ds, dx, dy) |= TILE_KEYBOARD_CURSOR;
  2645. if (gx == tx && gy == ty)
  2646. todraw(ds, dx, dy) |= TILE_ROTATING;
  2647. if (gx == ui->cx && gy == ui->cy) {
  2648. todraw(ds, dx, dy) |= 3 << TILE_ENDPOINT_SHIFT;
  2649. } else if ((t & 0xF) != R && (t & 0xF) != U &&
  2650. (t & 0xF) != L && (t & 0xF) != D) {
  2651. /* this is not an endpoint tile */
  2652. } else if (t & ACTIVE) {
  2653. todraw(ds, dx, dy) |= 2 << TILE_ENDPOINT_SHIFT;
  2654. } else {
  2655. todraw(ds, dx, dy) |= 1 << TILE_ENDPOINT_SHIFT;
  2656. }
  2657. if (t & LOCKED)
  2658. todraw(ds, dx, dy) |= TILE_LOCKED;
  2659. /*
  2660. * In a completion flash, we adjust the LOCKED bit
  2661. * depending on our distance from the centre point and
  2662. * the frame number.
  2663. */
  2664. if (frame >= 0) {
  2665. int rcx = (ui->cx + ds->width - ui->org_x) % ds->width;
  2666. int rcy = (ui->cy + ds->height - ui->org_y) % ds->height;
  2667. int xdist, ydist, dist;
  2668. xdist = (dx < rcx ? rcx - dx : dx - rcx);
  2669. ydist = (dy < rcy ? rcy - dy : dy - rcy);
  2670. dist = (xdist > ydist ? xdist : ydist);
  2671. if (frame >= dist && frame < dist+4 &&
  2672. ((frame - dist) & 1))
  2673. todraw(ds, dx, dy) ^= TILE_LOCKED;
  2674. }
  2675. }
  2676. }
  2677. /*
  2678. * Now draw any tile that differs from the way it was last drawn.
  2679. * An exception is that if either the previous _or_ current state
  2680. * has the TILE_ROTATING bit set, we must draw it regardless,
  2681. * because it will have rotated to a different angle.q
  2682. */
  2683. for (dy = -1; dy < ds->height+1; dy++) {
  2684. for (dx = -1; dx < ds->width+1; dx++) {
  2685. int prev = visible(ds, dx, dy);
  2686. int curr = todraw(ds, dx, dy);
  2687. if (prev != curr || ((prev | curr) & TILE_ROTATING) != 0) {
  2688. draw_tile(dr, ds, dx, dy, curr, angle);
  2689. visible(ds, dx, dy) = curr;
  2690. }
  2691. }
  2692. }
  2693. /*
  2694. * Update the status bar.
  2695. */
  2696. {
  2697. char statusbuf[256], *p;
  2698. int i, n, n2, a;
  2699. bool complete = false;
  2700. p = statusbuf;
  2701. *p = '\0'; /* ensure even an empty status string is terminated */
  2702. if (state->used_solve) {
  2703. p += sprintf(p, "Auto-solved. ");
  2704. complete = true;
  2705. } else if (state->completed) {
  2706. p += sprintf(p, "COMPLETED! ");
  2707. complete = true;
  2708. }
  2709. /*
  2710. * Omit the 'Active: n/N' counter completely if the source
  2711. * tile is a completely empty one, because then the active
  2712. * count can't help but read '1'.
  2713. */
  2714. if (tile(state, ui->cx, ui->cy) & 0xF) {
  2715. n = state->width * state->height;
  2716. for (i = a = n2 = 0; i < n; i++) {
  2717. if (active[i])
  2718. a++;
  2719. if (state->tiles[i] & 0xF)
  2720. n2++;
  2721. }
  2722. /*
  2723. * Also, if we're displaying a completion indicator and
  2724. * the game is still in its completed state (i.e. every
  2725. * tile is active), we might as well omit this too.
  2726. */
  2727. if (!complete || a < n2)
  2728. p += sprintf(p, "Active: %d/%d", a, n2);
  2729. }
  2730. status_bar(dr, statusbuf);
  2731. }
  2732. sfree(active);
  2733. sfree(loops);
  2734. }
  2735. static float game_anim_length(const game_state *oldstate,
  2736. const game_state *newstate, int dir, game_ui *ui)
  2737. {
  2738. int last_rotate_dir;
  2739. /*
  2740. * Don't animate if last_rotate_dir is zero.
  2741. */
  2742. last_rotate_dir = dir==-1 ? oldstate->last_rotate_dir :
  2743. newstate->last_rotate_dir;
  2744. if (last_rotate_dir)
  2745. return ROTATE_TIME;
  2746. return 0.0F;
  2747. }
  2748. static float game_flash_length(const game_state *oldstate,
  2749. const game_state *newstate, int dir, game_ui *ui)
  2750. {
  2751. /*
  2752. * If the game has just been completed, we display a completion
  2753. * flash.
  2754. */
  2755. if (!oldstate->completed && newstate->completed &&
  2756. !oldstate->used_solve && !newstate->used_solve) {
  2757. int size = 0;
  2758. if (size < newstate->width)
  2759. size = newstate->width;
  2760. if (size < newstate->height)
  2761. size = newstate->height;
  2762. return FLASH_FRAME * (size+4);
  2763. }
  2764. return 0.0F;
  2765. }
  2766. static void game_get_cursor_location(const game_ui *ui,
  2767. const game_drawstate *ds,
  2768. const game_state *state,
  2769. const game_params *params,
  2770. int *x, int *y, int *w, int *h)
  2771. {
  2772. if(ui->cur_visible) {
  2773. *x = WINDOW_OFFSET + TILE_SIZE * ui->cur_x;
  2774. *y = WINDOW_OFFSET + TILE_SIZE * ui->cur_y;
  2775. *w = *h = TILE_SIZE;
  2776. }
  2777. }
  2778. static int game_status(const game_state *state)
  2779. {
  2780. return state->completed ? +1 : 0;
  2781. }
  2782. static void game_print_size(const game_params *params, const game_ui *ui,
  2783. float *x, float *y)
  2784. {
  2785. int pw, ph;
  2786. /*
  2787. * I'll use 8mm squares by default.
  2788. */
  2789. game_compute_size(params, 800, ui, &pw, &ph);
  2790. *x = pw / 100.0F;
  2791. *y = ph / 100.0F;
  2792. }
  2793. static void draw_diagram(drawing *dr, game_drawstate *ds, int x, int y,
  2794. bool topleft, int v, bool drawlines, int ink)
  2795. {
  2796. int tx, ty, cx, cy, r, br, k, thick;
  2797. tx = WINDOW_OFFSET + TILE_SIZE * x;
  2798. ty = WINDOW_OFFSET + TILE_SIZE * y;
  2799. /*
  2800. * Find our centre point.
  2801. */
  2802. if (topleft) {
  2803. cx = tx + (v & L ? TILE_SIZE / 4 : TILE_SIZE / 6);
  2804. cy = ty + (v & U ? TILE_SIZE / 4 : TILE_SIZE / 6);
  2805. r = TILE_SIZE / 8;
  2806. br = TILE_SIZE / 32;
  2807. } else {
  2808. cx = tx + TILE_SIZE / 2;
  2809. cy = ty + TILE_SIZE / 2;
  2810. r = TILE_SIZE / 2;
  2811. br = TILE_SIZE / 8;
  2812. }
  2813. thick = r / 20;
  2814. /*
  2815. * Draw the square block if we have an endpoint.
  2816. */
  2817. if (v == 1 || v == 2 || v == 4 || v == 8)
  2818. draw_rect(dr, cx - br, cy - br, br*2, br*2, ink);
  2819. /*
  2820. * Draw each radial line.
  2821. */
  2822. if (drawlines) {
  2823. for (k = 1; k < 16; k *= 2)
  2824. if (v & k) {
  2825. int x1 = min(cx, cx + (r-thick) * X(k));
  2826. int x2 = max(cx, cx + (r-thick) * X(k));
  2827. int y1 = min(cy, cy + (r-thick) * Y(k));
  2828. int y2 = max(cy, cy + (r-thick) * Y(k));
  2829. draw_rect(dr, x1 - thick, y1 - thick,
  2830. (x2 - x1) + 2*thick, (y2 - y1) + 2*thick, ink);
  2831. }
  2832. }
  2833. }
  2834. static void game_print(drawing *dr, const game_state *state, const game_ui *ui,
  2835. int tilesize)
  2836. {
  2837. int w = state->width, h = state->height;
  2838. int ink = print_mono_colour(dr, 0);
  2839. int x, y;
  2840. /* Ick: fake up `ds->tilesize' for macro expansion purposes */
  2841. game_drawstate ads, *ds = &ads;
  2842. game_set_size(dr, ds, NULL, tilesize);
  2843. /*
  2844. * Border.
  2845. */
  2846. print_line_width(dr, TILE_SIZE / (state->wrapping ? 128 : 12));
  2847. draw_rect_outline(dr, WINDOW_OFFSET, WINDOW_OFFSET,
  2848. TILE_SIZE * w, TILE_SIZE * h, ink);
  2849. /*
  2850. * Grid.
  2851. */
  2852. print_line_width(dr, TILE_SIZE / 128);
  2853. for (x = 1; x < w; x++)
  2854. draw_line(dr, WINDOW_OFFSET + TILE_SIZE * x, WINDOW_OFFSET,
  2855. WINDOW_OFFSET + TILE_SIZE * x, WINDOW_OFFSET + TILE_SIZE * h,
  2856. ink);
  2857. for (y = 1; y < h; y++)
  2858. draw_line(dr, WINDOW_OFFSET, WINDOW_OFFSET + TILE_SIZE * y,
  2859. WINDOW_OFFSET + TILE_SIZE * w, WINDOW_OFFSET + TILE_SIZE * y,
  2860. ink);
  2861. /*
  2862. * Barriers.
  2863. */
  2864. for (y = 0; y <= h; y++)
  2865. for (x = 0; x <= w; x++) {
  2866. int b = barrier(state, x % w, y % h);
  2867. if (x < w && (b & U))
  2868. draw_rect(dr, WINDOW_OFFSET + TILE_SIZE * x - TILE_SIZE/24,
  2869. WINDOW_OFFSET + TILE_SIZE * y - TILE_SIZE/24,
  2870. TILE_SIZE + TILE_SIZE/24 * 2, TILE_SIZE/24 * 2, ink);
  2871. if (y < h && (b & L))
  2872. draw_rect(dr, WINDOW_OFFSET + TILE_SIZE * x - TILE_SIZE/24,
  2873. WINDOW_OFFSET + TILE_SIZE * y - TILE_SIZE/24,
  2874. TILE_SIZE/24 * 2, TILE_SIZE + TILE_SIZE/24 * 2, ink);
  2875. }
  2876. /*
  2877. * Grid contents.
  2878. */
  2879. for (y = 0; y < h; y++)
  2880. for (x = 0; x < w; x++) {
  2881. int vx, v = tile(state, x, y);
  2882. int locked = v & LOCKED;
  2883. v &= 0xF;
  2884. /*
  2885. * Rotate into a standard orientation for the top left
  2886. * corner diagram.
  2887. */
  2888. vx = v;
  2889. while (vx != 0 && vx != 15 && vx != 1 && vx != 9 && vx != 13 &&
  2890. vx != 5)
  2891. vx = A(vx);
  2892. /*
  2893. * Draw the top left corner diagram.
  2894. */
  2895. draw_diagram(dr, ds, x, y, true, vx, true, ink);
  2896. /*
  2897. * Draw the real solution diagram, if we're doing so.
  2898. */
  2899. draw_diagram(dr, ds, x, y, false, v, locked, ink);
  2900. }
  2901. }
  2902. #ifdef COMBINED
  2903. #define thegame net
  2904. #endif
  2905. const struct game thegame = {
  2906. "Net", "games.net", "net",
  2907. default_params,
  2908. game_fetch_preset, NULL,
  2909. decode_params,
  2910. encode_params,
  2911. free_params,
  2912. dup_params,
  2913. true, game_configure, custom_params,
  2914. validate_params,
  2915. new_game_desc,
  2916. validate_desc,
  2917. new_game,
  2918. dup_game,
  2919. free_game,
  2920. true, solve_game,
  2921. false, NULL, NULL, /* can_format_as_text_now, text_format */
  2922. get_prefs, set_prefs,
  2923. new_ui,
  2924. free_ui,
  2925. encode_ui,
  2926. decode_ui,
  2927. NULL, /* game_request_keys */
  2928. game_changed_state,
  2929. current_key_label,
  2930. interpret_move,
  2931. execute_move,
  2932. PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
  2933. game_colours,
  2934. game_new_drawstate,
  2935. game_free_drawstate,
  2936. game_redraw,
  2937. game_anim_length,
  2938. game_flash_length,
  2939. game_get_cursor_location,
  2940. game_status,
  2941. true, false, game_print_size, game_print,
  2942. true, /* wants_statusbar */
  2943. false, NULL, /* timing_state */
  2944. 0, /* flags */
  2945. };