Advertisement
Guest User

Untitled

a guest
Apr 6th, 2018
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. <!DOCTYPE HTML>
  3. <html>
  4.  
  5. <!-- HEADER -->
  6. <head>
  7.  
  8. <title>Write your game's title here</title>
  9.  
  10. <script type="bitsyGameData" id="exportedGameData">
  11. Write your game's title here
  12.  
  13. # BITSY VERSION 4.6
  14.  
  15. ! ROOM_FORMAT 1
  16.  
  17. PAL 0
  18. 0,82,204
  19. 128,159,255
  20. 255,255,255
  21.  
  22. ROOM 0
  23. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  24. 0,a,a,a,a,a,a,a,a,a,a,a,a,a,a,0
  25. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  26. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  27. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  28. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  29. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  30. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  31. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  32. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  33. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  34. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  35. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  36. 0,a,0,0,0,0,0,0,0,0,0,0,0,0,a,0
  37. 0,a,a,a,a,a,a,a,a,a,a,a,a,a,a,0
  38. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  39. PAL 0
  40.  
  41. TIL a
  42. 11111111
  43. 10000001
  44. 10000001
  45. 10011001
  46. 10011001
  47. 10000001
  48. 10000001
  49. 11111111
  50.  
  51. SPR A
  52. 00011000
  53. 00011000
  54. 00011000
  55. 00111100
  56. 01111110
  57. 10111101
  58. 00100100
  59. 00100100
  60. POS 0 4,4
  61.  
  62. SPR a
  63. 00000000
  64. 00000000
  65. 01010001
  66. 01110001
  67. 01110010
  68. 01111100
  69. 00111100
  70. 00100100
  71. DLG SPR_0
  72. POS 0 8,12
  73.  
  74. ITM 0
  75. 00000000
  76. 00000000
  77. 00000000
  78. 00111100
  79. 01100100
  80. 00100100
  81. 00011000
  82. 00000000
  83. NAME tea
  84. DLG ITM_0
  85.  
  86. DLG SPR_0
  87. I'm a cat
  88.  
  89. DLG ITM_0
  90. You found a nice warm cup of tea
  91.  
  92. VAR a
  93. 42
  94.  
  95.  
  96. </script>
  97.  
  98. <style>
  99. html {
  100.     margin:0px;
  101.     padding:0px;
  102. }
  103.  
  104. body {
  105.     margin:0px;
  106.     padding:0px;
  107.     overflow:hidden;
  108.     background:#ffffff;
  109. }
  110.  
  111. #game {
  112.     background:black;
  113.     width:100vw;
  114.     max-width:100vh;
  115.     margin:auto;
  116.     display:block;
  117. }
  118. </style>
  119.  
  120. <!-- SCRIPTS -->
  121. <script>
  122. function startExportedGame() {
  123.     attachCanvas( document.getElementById("game") );
  124.     load_game( document.getElementById("exportedGameData").text.slice(1) );
  125. }
  126. </script>
  127.  
  128. <script>
  129. //hex-to-rgb method borrowed from stack overflow
  130. function hexToRgb(hex) {
  131.     // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  132.     var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  133.     hex = hex.replace(shorthandRegex, function(m, r, g, b) {
  134.         return r + r + g + g + b + b;
  135.     });
  136.  
  137.     var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  138.     return result ? {
  139.         r: parseInt(result[1], 16),
  140.         g: parseInt(result[2], 16),
  141.         b: parseInt(result[3], 16)
  142.     } : null;
  143. }
  144. function componentToHex(c) {
  145.    var hex = c.toString(16);
  146.    return hex.length == 1 ? "0" + hex : hex;
  147. }
  148. function rgbToHex(r, g, b) {
  149.    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
  150. }
  151.  
  152.  
  153. // source : http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
  154. /* accepts parameters
  155. * h  Object = {h:x, s:y, v:z}
  156. * OR
  157. * h, s, v
  158. */
  159. function HSVtoRGB(h, s, v) {
  160.    var r, g, b, i, f, p, q, t;
  161.    if (arguments.length === 1) {
  162.        s = h.s, v = h.v, h = h.h;
  163.    }
  164.    i = Math.floor(h * 6);
  165.    f = h * 6 - i;
  166.    p = v * (1 - s);
  167.    q = v * (1 - f * s);
  168.    t = v * (1 - (1 - f) * s);
  169.    switch (i % 6) {
  170.        case 0: r = v, g = t, b = p; break;
  171.        case 1: r = q, g = v, b = p; break;
  172.        case 2: r = p, g = v, b = t; break;
  173.        case 3: r = p, g = q, b = v; break;
  174.        case 4: r = t, g = p, b = v; break;
  175.        case 5: r = v, g = p, b = q; break;
  176.    }
  177.    return {
  178.        r: Math.round(r * 255),
  179.        g: Math.round(g * 255),
  180.        b: Math.round(b * 255)
  181.    };
  182. }
  183.  
  184. /* accepts parameters
  185. * r  Object = {r:x, g:y, b:z}
  186. * OR
  187. * r, g, b
  188. */
  189. function RGBtoHSV(r, g, b) {
  190.    if (arguments.length === 1) {
  191.        g = r.g, b = r.b, r = r.r;
  192.    }
  193.    var max = Math.max(r, g, b), min = Math.min(r, g, b),
  194.        d = max - min,
  195.        h,
  196.        s = (max === 0 ? 0 : d / max),
  197.        v = max / 255;
  198.  
  199.    switch (max) {
  200.        case min: h = 0; break;
  201.        case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
  202.        case g: h = (b - r) + d * 2; h /= 6 * d; break;
  203.        case b: h = (r - g) + d * 4; h /= 6 * d; break;
  204.    }
  205.  
  206.    return {
  207.        h: h,
  208.        s: s,
  209.        v: v
  210.    };
  211. }
  212.  
  213. // source : https://gist.github.com/mjackson/5311256
  214. /**
  215. * Converts an HSL color value to RGB. Conversion formula
  216. * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
  217. * Assumes h, s, and l are contained in the set [0, 1] and
  218. * returns r, g, and b in the set [0, 255].
  219. *
  220. * @param   Number  h       The hue
  221. * @param   Number  s       The saturation
  222. * @param   Number  l       The lightness
  223. * @return  Array           The RGB representation
  224. */
  225. function hslToRgb(h, s, l) {
  226.  var r, g, b;
  227.  
  228.  if (s == 0) {
  229.    r = g = b = l; // achromatic
  230.  } else {
  231.    function hue2rgb(p, q, t) {
  232.      if (t < 0) t += 1;
  233.      if (t > 1) t -= 1;
  234.      if (t < 1/6) return p + (q - p) * 6 * t;
  235.      if (t < 1/2) return q;
  236.      if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
  237.      return p;
  238.    }
  239.  
  240.    var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  241.    var p = 2 * l - q;
  242.  
  243.    r = hue2rgb(p, q, h + 1/3);
  244.    g = hue2rgb(p, q, h);
  245.    b = hue2rgb(p, q, h - 1/3);
  246.  }
  247.  
  248.  return [ r * 255, g * 255, b * 255 ];
  249. }
  250.  
  251. /**
  252. * From: http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
  253. *
  254. * Converts an RGB color value to HSL. Conversion formula
  255. * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
  256. * Assumes r, g, and b are contained in the set [0, 255] and
  257. * returns h, s, and l in the set [0, 1].
  258. *
  259. * @param   {number}  r       The red color value
  260. * @param   {number}  g       The green color value
  261. * @param   {number}  b       The blue color value
  262. * @return  {Array}           The HSL representation
  263. */
  264. function rgbToHsl(r, g, b){
  265.    r /= 255, g /= 255, b /= 255;
  266.    var max = Math.max(r, g, b), min = Math.min(r, g, b);
  267.    var h, s, l = (max + min) / 2;
  268.  
  269.    if(max == min){
  270.        h = s = 0; // achromatic
  271.    }else{
  272.        var d = max - min;
  273.        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  274.        switch(max){
  275.            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  276.            case g: h = (b - r) / d + 2; break;
  277.            case b: h = (r - g) / d + 4; break;
  278.        }
  279.        h /= 6;
  280.    }
  281.  
  282.    return [h, s, l];
  283. }
  284. </script>
  285.  
  286. <script>
  287. function Font() {
  288.  
  289.  
  290. this.getData = function() {
  291.     return fontdata;
  292. }
  293.  
  294. var charSize = 6 * 8;
  295. this.getChar = function(char) {
  296.     var startIndex = char.charCodeAt(0) * charSize;
  297.     return fontdata.slice( startIndex, startIndex + charSize );
  298. }
  299.  
  300. var fontdata = [
  301.         /* num: 0 */
  302.         0,0,0,0,0,0,
  303.         0,0,0,0,0,0,
  304.         0,0,0,0,0,0,
  305.         0,0,0,0,0,0,
  306.         0,0,0,0,0,0,
  307.         0,0,0,0,0,0,
  308.         0,0,0,0,0,0,
  309.         0,0,0,0,0,0,
  310.         /* num: 1 */
  311.         0,0,1,1,1,0,
  312.         0,1,0,0,0,1,
  313.         0,1,1,0,1,1,
  314.         0,1,0,0,0,1,
  315.         0,1,0,1,0,1,
  316.         0,1,0,0,0,1,
  317.         0,0,1,1,1,0,
  318.         0,0,0,0,0,0,
  319.         /* num: 2 */
  320.         0,0,1,1,1,0,
  321.         0,1,1,1,1,1,
  322.         0,1,0,1,0,1,
  323.         0,1,1,1,1,1,
  324.         0,1,0,0,0,1,
  325.         0,1,1,1,1,1,
  326.         0,0,1,1,1,0,
  327.         0,0,0,0,0,0,
  328.         /* num: 3 */
  329.         0,0,0,0,0,0,
  330.         0,0,1,0,1,0,
  331.         0,1,1,1,1,1,
  332.         0,1,1,1,1,1,
  333.         0,1,1,1,1,1,
  334.         0,0,1,1,1,0,
  335.         0,0,0,1,0,0,
  336.         0,0,0,0,0,0,
  337.         /* num: 4 */
  338.         0,0,0,0,0,0,
  339.         0,0,0,0,0,0,
  340.         0,0,1,0,1,0,
  341.         0,0,1,1,1,0,
  342.         0,0,1,1,1,0,
  343.         0,0,0,1,0,0,
  344.         0,0,0,0,0,0,
  345.         0,0,0,0,0,0,
  346.         /*0,0,0,0,0,0,
  347.         0,0,1,0,1,0,
  348.         0,1,0,1,0,1,
  349.         0,1,0,0,0,1,
  350.         0,1,0,0,0,1,
  351.         0,0,1,0,1,0,
  352.         0,0,0,1,0,0,
  353.         0,0,0,0,0,0,*/
  354.         /* num: 5 */
  355.         0,0,0,1,0,0,
  356.         0,0,1,1,1,0,
  357.         0,0,1,1,1,0,
  358.         0,0,0,1,0,0,
  359.         0,1,1,1,1,1,
  360.         0,1,1,1,1,1,
  361.         0,0,0,1,0,0,
  362.         0,0,0,0,0,0,
  363.         /* num: 6 */
  364.         0,0,0,0,0,0,
  365.         0,0,0,1,0,0,
  366.         0,0,1,1,1,0,
  367.         0,1,1,1,1,1,
  368.         0,1,1,1,1,1,
  369.         0,0,0,1,0,0,
  370.         0,0,1,1,1,0,
  371.         0,0,0,0,0,0,
  372.         /* num: 7 */
  373.         0,0,0,0,0,0,
  374.         0,0,0,0,0,0,
  375.         0,0,0,0,0,0,
  376.         0,0,1,1,0,0,
  377.         0,0,1,1,0,0,
  378.         0,0,0,0,0,0,
  379.         0,0,0,0,0,0,
  380.         0,0,0,0,0,0,
  381.         /* num: 8 */
  382.         1,1,1,1,1,1,
  383.         1,1,1,1,1,1,
  384.         1,1,1,1,1,1,
  385.         1,1,0,0,1,1,
  386.         1,1,0,0,1,1,
  387.         1,1,1,1,1,1,
  388.         1,1,1,1,1,1,
  389.         1,1,1,1,1,1,
  390.         /* num: 9 */
  391.         0,0,0,0,0,0,
  392.         0,0,0,0,0,0,
  393.         0,1,1,1,1,0,
  394.         0,1,0,0,1,0,
  395.         0,1,0,0,1,0,
  396.         0,1,1,1,1,0,
  397.         0,0,0,0,0,0,
  398.         0,0,0,0,0,0,
  399.         /* num: 10 */
  400.         1,1,1,1,1,1,
  401.         1,1,1,1,1,1,
  402.         1,0,0,0,0,1,
  403.         1,0,1,1,0,1,
  404.         1,0,1,1,0,1,
  405.         1,0,0,0,0,1,
  406.         1,1,1,1,1,1,
  407.         1,1,1,1,1,1,
  408.         /* num: 11 */
  409.         0,0,0,0,0,0,
  410.         0,0,0,1,1,1,
  411.         0,0,0,0,1,1,
  412.         0,0,1,1,0,1,
  413.         0,1,0,0,1,0,
  414.         0,1,0,0,1,0,
  415.         0,0,1,1,0,0,
  416.         0,0,0,0,0,0,
  417.         /* num: 12 */
  418.         0,0,1,1,1,0,
  419.         0,1,0,0,0,1,
  420.         0,1,0,0,0,1,
  421.         0,0,1,1,1,0,
  422.         0,0,0,1,0,0,
  423.         0,0,1,1,1,0,
  424.         0,0,0,1,0,0,
  425.         0,0,0,0,0,0,
  426.         /* num: 13 */
  427.         0,0,0,1,0,0,
  428.         0,0,0,1,1,0,
  429.         0,0,0,1,0,1,
  430.         0,0,0,1,0,0,
  431.         0,0,1,1,0,0,
  432.         0,1,1,1,0,0,
  433.         0,1,1,0,0,0,
  434.         0,0,0,0,0,0,
  435.         /* num: 14 */
  436.         0,0,0,0,1,1,
  437.         0,0,1,1,0,1,
  438.         0,0,1,0,1,1,
  439.         0,0,1,1,0,1,
  440.         0,0,1,0,1,1,
  441.         0,1,1,0,1,1,
  442.         0,1,1,0,0,0,
  443.         0,0,0,0,0,0,
  444.         /* num: 15 */
  445.         0,0,0,0,0,0,
  446.         0,1,0,1,0,1,
  447.         0,0,1,1,1,0,
  448.         0,1,1,0,1,1,
  449.         0,0,1,1,1,0,
  450.         0,1,0,1,0,1,
  451.         0,0,0,0,0,0,
  452.         0,0,0,0,0,0,
  453.         /* num: 16 */
  454.         0,0,1,0,0,0,
  455.         0,0,1,1,0,0,
  456.         0,0,1,1,1,0,
  457.         0,0,1,1,1,1,
  458.         0,0,1,1,1,0,
  459.         0,0,1,1,0,0,
  460.         0,0,1,0,0,0,
  461.         0,0,0,0,0,0,
  462.         /* num: 17 */
  463.         0,0,0,0,1,0,
  464.         0,0,0,1,1,0,
  465.         0,0,1,1,1,0,
  466.         0,1,1,1,1,0,
  467.         0,0,1,1,1,0,
  468.         0,0,0,1,1,0,
  469.         0,0,0,0,1,0,
  470.         0,0,0,0,0,0,
  471.         /* num: 18 */
  472.         0,0,0,1,0,0,
  473.         0,0,1,1,1,0,
  474.         0,1,1,1,1,1,
  475.         0,0,0,1,0,0,
  476.         0,1,1,1,1,1,
  477.         0,0,1,1,1,0,
  478.         0,0,0,1,0,0,
  479.         0,0,0,0,0,0,
  480.         /* num: 19 */
  481.         0,0,1,0,1,0,
  482.         0,0,1,0,1,0,
  483.         0,0,1,0,1,0,
  484.         0,0,1,0,1,0,
  485.         0,0,1,0,1,0,
  486.         0,0,0,0,0,0,
  487.         0,0,1,0,1,0,
  488.         0,0,0,0,0,0,
  489.         /* num: 20 */
  490.         0,0,1,1,1,1,
  491.         0,1,0,1,0,1,
  492.         0,1,0,1,0,1,
  493.         0,0,1,1,0,1,
  494.         0,0,0,1,0,1,
  495.         0,0,0,1,0,1,
  496.         0,0,0,1,0,1,
  497.         0,0,0,0,0,0,
  498.         /* num: 21 */
  499.         0,0,1,1,1,0,
  500.         0,1,0,0,0,1,
  501.         0,0,1,1,0,0,
  502.         0,0,1,0,1,0,
  503.         0,0,0,1,1,0,
  504.         0,1,0,0,0,1,
  505.         0,0,1,1,1,0,
  506.         0,0,0,0,0,0,
  507.         /* num: 22 */
  508.         0,0,0,0,0,0,
  509.         0,0,0,0,0,0,
  510.         0,0,0,0,0,0,
  511.         0,0,0,0,0,0,
  512.         0,0,0,0,0,0,
  513.         0,1,1,1,1,0,
  514.         0,1,1,1,1,0,
  515.         0,0,0,0,0,0,
  516.         /* num: 23 */
  517.         0,0,0,1,0,0,
  518.         0,0,1,1,1,0,
  519.         0,1,1,1,1,1,
  520.         0,0,0,1,0,0,
  521.         0,1,1,1,1,1,
  522.         0,0,1,1,1,0,
  523.         0,0,0,1,0,0,
  524.         0,0,1,1,1,0,
  525.         /* num: 24 */
  526.         0,0,0,1,0,0,
  527.         0,0,1,1,1,0,
  528.         0,1,1,1,1,1,
  529.         0,0,0,1,0,0,
  530.         0,0,0,1,0,0,
  531.         0,0,0,1,0,0,
  532.         0,0,0,1,0,0,
  533.         0,0,0,0,0,0,
  534.         /* num: 25 */
  535.         0,0,0,1,0,0,
  536.         0,0,0,1,0,0,
  537.         0,0,0,1,0,0,
  538.         0,0,0,1,0,0,
  539.         0,1,1,1,1,1,
  540.         0,0,1,1,1,0,
  541.         0,0,0,1,0,0,
  542.         0,0,0,0,0,0,
  543.         /* num: 26 */
  544.         0,0,0,0,0,0,
  545.         0,0,0,1,0,0,
  546.         0,0,0,1,1,0,
  547.         0,1,1,1,1,1,
  548.         0,0,0,1,1,0,
  549.         0,0,0,1,0,0,
  550.         0,0,0,0,0,0,
  551.         0,0,0,0,0,0,
  552.         /* num: 27 */
  553.         0,0,0,0,0,0,
  554.         0,0,0,1,0,0,
  555.         0,0,1,1,0,0,
  556.         0,1,1,1,1,1,
  557.         0,0,1,1,0,0,
  558.         0,0,0,1,0,0,
  559.         0,0,0,0,0,0,
  560.         0,0,0,0,0,0,
  561.         /* num: 28 */
  562.         0,0,0,0,0,0,
  563.         0,0,0,0,0,0,
  564.         0,0,0,0,0,0,
  565.         0,1,0,0,0,0,
  566.         0,1,0,0,0,0,
  567.         0,1,0,0,0,0,
  568.         0,1,1,1,1,1,
  569.         0,0,0,0,0,0,
  570.         /* num: 29 */
  571.         0,0,0,0,0,0,
  572.         0,0,1,0,1,0,
  573.         0,0,1,0,1,0,
  574.         0,1,1,1,1,1,
  575.         0,0,1,0,1,0,
  576.         0,0,1,0,1,0,
  577.         0,0,0,0,0,0,
  578.         0,0,0,0,0,0,
  579.         /* num: 30 */
  580.         0,0,0,1,0,0,
  581.         0,0,0,1,0,0,
  582.         0,0,1,1,1,0,
  583.         0,0,1,1,1,0,
  584.         0,1,1,1,1,1,
  585.         0,1,1,1,1,1,
  586.         0,0,0,0,0,0,
  587.         0,0,0,0,0,0,
  588.         /* num: 31 */
  589.         0,1,1,1,1,1,
  590.         0,1,1,1,1,1,
  591.         0,0,1,1,1,0,
  592.         0,0,1,1,1,0,
  593.         0,0,0,1,0,0,
  594.         0,0,0,1,0,0,
  595.         0,0,0,0,0,0,
  596.         0,0,0,0,0,0,
  597.         /* num: 32 */
  598.         0,0,0,0,0,0,
  599.         0,0,0,0,0,0,
  600.         0,0,0,0,0,0,
  601.         0,0,0,0,0,0,
  602.         0,0,0,0,0,0,
  603.         0,0,0,0,0,0,
  604.         0,0,0,0,0,0,
  605.         0,0,0,0,0,0,
  606.         /* num: 33 */
  607.         0,0,0,1,0,0,
  608.         0,0,1,1,1,0,
  609.         0,0,1,1,1,0,
  610.         0,0,0,1,0,0,
  611.         0,0,0,1,0,0,
  612.         0,0,0,0,0,0,
  613.         0,0,0,1,0,0,
  614.         0,0,0,0,0,0,
  615.         /* num: 34 */
  616.         0,1,1,0,1,1,
  617.         0,1,1,0,1,1,
  618.         0,1,0,0,1,0,
  619.         0,0,0,0,0,0,
  620.         0,0,0,0,0,0,
  621.         0,0,0,0,0,0,
  622.         0,0,0,0,0,0,
  623.         0,0,0,0,0,0,
  624.         /* num: 35 */
  625.         0,0,0,0,0,0,
  626.         0,0,1,0,1,0,
  627.         0,1,1,1,1,1,
  628.         0,0,1,0,1,0,
  629.         0,0,1,0,1,0,
  630.         0,1,1,1,1,1,
  631.         0,0,1,0,1,0,
  632.         0,0,0,0,0,0,
  633.         /* num: 36 */
  634.         0,0,1,0,0,0,
  635.         0,0,1,1,1,0,
  636.         0,1,0,0,0,0,
  637.         0,0,1,1,0,0,
  638.         0,0,0,0,1,0,
  639.         0,1,1,1,0,0,
  640.         0,0,0,1,0,0,
  641.         0,0,0,0,0,0,
  642.         /* num: 37 */
  643.         0,1,1,0,0,1,
  644.         0,1,1,0,0,1,
  645.         0,0,0,0,1,0,
  646.         0,0,0,1,0,0,
  647.         0,0,1,0,0,0,
  648.         0,1,0,0,1,1,
  649.         0,1,0,0,1,1,
  650.         0,0,0,0,0,0,
  651.         /* num: 38 */
  652.         0,0,1,0,0,0,
  653.         0,1,0,1,0,0,
  654.         0,1,0,1,0,0,
  655.         0,0,1,0,0,0,
  656.         0,1,0,1,0,1,
  657.         0,1,0,0,1,0,
  658.         0,0,1,1,0,1,
  659.         0,0,0,0,0,0,
  660.         /* num: 39 */
  661.         0,0,1,1,0,0,
  662.         0,0,1,1,0,0,
  663.         0,0,1,0,0,0,
  664.         0,0,0,0,0,0,
  665.         0,0,0,0,0,0,
  666.         0,0,0,0,0,0,
  667.         0,0,0,0,0,0,
  668.         0,0,0,0,0,0,
  669.         /* num: 40 */
  670.         0,0,0,1,0,0,
  671.         0,0,1,0,0,0,
  672.         0,0,1,0,0,0,
  673.         0,0,1,0,0,0,
  674.         0,0,1,0,0,0,
  675.         0,0,1,0,0,0,
  676.         0,0,0,1,0,0,
  677.         0,0,0,0,0,0,
  678.         /* num: 41 */
  679.         0,0,1,0,0,0,
  680.         0,0,0,1,0,0,
  681.         0,0,0,1,0,0,
  682.         0,0,0,1,0,0,
  683.         0,0,0,1,0,0,
  684.         0,0,0,1,0,0,
  685.         0,0,1,0,0,0,
  686.         0,0,0,0,0,0,
  687.         /* num: 42 */
  688.         0,0,0,0,0,0,
  689.         0,0,1,0,1,0,
  690.         0,0,1,1,1,0,
  691.         0,1,1,1,1,1,
  692.         0,0,1,1,1,0,
  693.         0,0,1,0,1,0,
  694.         0,0,0,0,0,0,
  695.         0,0,0,0,0,0,
  696.         /* num: 43 */
  697.         0,0,0,0,0,0,
  698.         0,0,0,1,0,0,
  699.         0,0,0,1,0,0,
  700.         0,1,1,1,1,1,
  701.         0,0,0,1,0,0,
  702.         0,0,0,1,0,0,
  703.         0,0,0,0,0,0,
  704.         0,0,0,0,0,0,
  705.         /* num: 44 */
  706.         0,0,0,0,0,0,
  707.         0,0,0,0,0,0,
  708.         0,0,0,0,0,0,
  709.         0,0,0,0,0,0,
  710.         0,0,0,0,0,0,
  711.         0,0,1,1,0,0,
  712.         0,0,1,1,0,0,
  713.         0,0,1,0,0,0,
  714.         /* num: 45 */
  715.         0,0,0,0,0,0,
  716.         0,0,0,0,0,0,
  717.         0,0,0,0,0,0,
  718.         0,1,1,1,1,1,
  719.         0,0,0,0,0,0,
  720.         0,0,0,0,0,0,
  721.         0,0,0,0,0,0,
  722.         0,0,0,0,0,0,
  723.         /* num: 46 */
  724.         0,0,0,0,0,0,
  725.         0,0,0,0,0,0,
  726.         0,0,0,0,0,0,
  727.         0,0,0,0,0,0,
  728.         0,0,0,0,0,0,
  729.         0,0,1,1,0,0,
  730.         0,0,1,1,0,0,
  731.         0,0,0,0,0,0,
  732.         /* num: 47 */
  733.         0,0,0,0,0,0,
  734.         0,0,0,0,0,1,
  735.         0,0,0,0,1,0,
  736.         0,0,0,1,0,0,
  737.         0,0,1,0,0,0,
  738.         0,1,0,0,0,0,
  739.         0,0,0,0,0,0,
  740.         0,0,0,0,0,0,
  741.         /* num: 48 ZERO!!!!*/
  742.         0,0,1,1,1,0,
  743.         0,1,0,0,0,1,
  744.         0,1,0,0,1,1,
  745.         0,1,0,1,0,1,
  746.         0,1,1,0,0,1,
  747.         0,1,0,0,0,1,
  748.         0,0,1,1,1,0,
  749.         0,0,0,0,0,0,
  750.         /* num: 49 */
  751.         0,0,0,1,0,0,
  752.         0,0,1,1,0,0,
  753.         0,0,0,1,0,0,
  754.         0,0,0,1,0,0,
  755.         0,0,0,1,0,0,
  756.         0,0,0,1,0,0,
  757.         0,0,1,1,1,0,
  758.         0,0,0,0,0,0,
  759.         /* num: 50 */
  760.         0,0,1,1,1,0,
  761.         0,1,0,0,0,1,
  762.         0,0,0,0,0,1,
  763.         0,0,0,1,1,0,
  764.         0,0,1,0,0,0,
  765.         0,1,0,0,0,0,
  766.         0,1,1,1,1,1,
  767.         0,0,0,0,0,0,
  768.         /* num: 51 */
  769.         0,0,1,1,1,0,
  770.         0,1,0,0,0,1,
  771.         0,0,0,0,0,1,
  772.         0,0,1,1,1,0,
  773.         0,0,0,0,0,1,
  774.         0,1,0,0,0,1,
  775.         0,0,1,1,1,0,
  776.         0,0,0,0,0,0,
  777.         /* num: 52 */
  778.         0,0,0,0,1,0,
  779.         0,0,0,1,1,0,
  780.         0,0,1,0,1,0,
  781.         0,1,0,0,1,0,
  782.         0,1,1,1,1,1,
  783.         0,0,0,0,1,0,
  784.         0,0,0,0,1,0,
  785.         0,0,0,0,0,0,
  786.         /* num: 53 */
  787.         0,1,1,1,1,1,
  788.         0,1,0,0,0,0,
  789.         0,1,0,0,0,0,
  790.         0,1,1,1,1,0,
  791.         0,0,0,0,0,1,
  792.         0,1,0,0,0,1,
  793.         0,0,1,1,1,0,
  794.         0,0,0,0,0,0,
  795.         /* num: 54 */
  796.         0,0,0,1,1,0,
  797.         0,0,1,0,0,0,
  798.         0,1,0,0,0,0,
  799.         0,1,1,1,1,0,
  800.         0,1,0,0,0,1,
  801.         0,1,0,0,0,1,
  802.         0,0,1,1,1,0,
  803.         0,0,0,0,0,0,
  804.         /* num: 55 */
  805.         0,1,1,1,1,1,
  806.         0,0,0,0,0,1,
  807.         0,0,0,0,1,0,
  808.         0,0,0,1,0,0,
  809.         0,0,1,0,0,0,
  810.         0,0,1,0,0,0,
  811.         0,0,1,0,0,0,
  812.         0,0,0,0,0,0,
  813.         /* num: 56 */
  814.         0,0,1,1,1,0,
  815.         0,1,0,0,0,1,
  816.         0,1,0,0,0,1,
  817.         0,0,1,1,1,0,
  818.         0,1,0,0,0,1,
  819.         0,1,0,0,0,1,
  820.         0,0,1,1,1,0,
  821.         0,0,0,0,0,0,
  822.         /* num: 57 */
  823.         0,0,1,1,1,0,
  824.         0,1,0,0,0,1,
  825.         0,1,0,0,0,1,
  826.         0,0,1,1,1,1,
  827.         0,0,0,0,0,1,
  828.         0,0,0,0,1,0,
  829.         0,0,1,1,0,0,
  830.         0,0,0,0,0,0,
  831.         /* num: 58 */
  832.         0,0,0,0,0,0,
  833.         0,0,0,0,0,0,
  834.         0,0,1,1,0,0,
  835.         0,0,1,1,0,0,
  836.         0,0,0,0,0,0,
  837.         0,0,1,1,0,0,
  838.         0,0,1,1,0,0,
  839.         0,0,0,0,0,0,
  840.         /* num: 59 */
  841.         0,0,0,0,0,0,
  842.         0,0,0,0,0,0,
  843.         0,0,1,1,0,0,
  844.         0,0,1,1,0,0,
  845.         0,0,0,0,0,0,
  846.         0,0,1,1,0,0,
  847.         0,0,1,1,0,0,
  848.         0,0,1,0,0,0,
  849.         /* num: 60 */
  850.         0,0,0,0,1,0,
  851.         0,0,0,1,0,0,
  852.         0,0,1,0,0,0,
  853.         0,1,0,0,0,0,
  854.         0,0,1,0,0,0,
  855.         0,0,0,1,0,0,
  856.         0,0,0,0,1,0,
  857.         0,0,0,0,0,0,
  858.         /* num: 61 */
  859.         0,0,0,0,0,0,
  860.         0,0,0,0,0,0,
  861.         0,1,1,1,1,1,
  862.         0,0,0,0,0,0,
  863.         0,0,0,0,0,0,
  864.         0,1,1,1,1,1,
  865.         0,0,0,0,0,0,
  866.         0,0,0,0,0,0,
  867.         /* num: 62 */
  868.         0,0,1,0,0,0,
  869.         0,0,0,1,0,0,
  870.         0,0,0,0,1,0,
  871.         0,0,0,0,0,1,
  872.         0,0,0,0,1,0,
  873.         0,0,0,1,0,0,
  874.         0,0,1,0,0,0,
  875.         0,0,0,0,0,0,
  876.         /* num: 63 */
  877.         0,0,1,1,1,0,
  878.         0,1,0,0,0,1,
  879.         0,0,0,0,0,1,
  880.         0,0,0,1,1,0,
  881.         0,0,0,1,0,0,
  882.         0,0,0,0,0,0,
  883.         0,0,0,1,0,0,
  884.         0,0,0,0,0,0,
  885.         /* num: 64 */
  886.         0,0,1,1,1,0,
  887.         0,1,0,0,0,1,
  888.         0,1,0,1,1,1,
  889.         0,1,0,1,0,1,
  890.         0,1,0,1,1,1,
  891.         0,1,0,0,0,0,
  892.         0,0,1,1,1,0,
  893.         0,0,0,0,0,0,
  894.         /* num: 65 Start of Capital Letters*/
  895.         0,0,1,1,1,0,
  896.         0,1,0,0,0,1,
  897.         0,1,0,0,0,1,
  898.         0,1,0,0,0,1,
  899.         0,1,1,1,1,1,
  900.         0,1,0,0,0,1,
  901.         0,1,0,0,0,1,
  902.         0,0,0,0,0,0,
  903.         /* num: 66 */
  904.         0,1,1,1,1,0,
  905.         0,1,0,0,0,1,
  906.         0,1,0,0,0,1,
  907.         0,1,1,1,1,0,
  908.         0,1,0,0,0,1,
  909.         0,1,0,0,0,1,
  910.         0,1,1,1,1,0,
  911.         0,0,0,0,0,0,
  912.         /* num: 67 */
  913.         0,0,1,1,1,0,
  914.         0,1,0,0,0,1,
  915.         0,1,0,0,0,0,
  916.         0,1,0,0,0,0,
  917.         0,1,0,0,0,0,
  918.         0,1,0,0,0,1,
  919.         0,0,1,1,1,0,
  920.         0,0,0,0,0,0,
  921.         /* num: 68 */
  922.         0,1,1,1,1,0,
  923.         0,1,0,0,0,1,
  924.         0,1,0,0,0,1,
  925.         0,1,0,0,0,1,
  926.         0,1,0,0,0,1,
  927.         0,1,0,0,0,1,
  928.         0,1,1,1,1,0,
  929.         0,0,0,0,0,0,
  930.         /* num: 69 */
  931.         0,1,1,1,1,1,
  932.         0,1,0,0,0,0,
  933.         0,1,0,0,0,0,
  934.         0,1,1,1,1,0,
  935.         0,1,0,0,0,0,
  936.         0,1,0,0,0,0,
  937.         0,1,1,1,1,1,
  938.         0,0,0,0,0,0,
  939.         /* num: 70 */
  940.         0,1,1,1,1,1,
  941.         0,1,0,0,0,0,
  942.         0,1,0,0,0,0,
  943.         0,1,1,1,1,0,
  944.         0,1,0,0,0,0,
  945.         0,1,0,0,0,0,
  946.         0,1,0,0,0,0,
  947.         0,0,0,0,0,0,
  948.         /* num: 71 */
  949.         0,0,1,1,1,0,
  950.         0,1,0,0,0,1,
  951.         0,1,0,0,0,0,
  952.         0,1,0,1,1,1,
  953.         0,1,0,0,0,1,
  954.         0,1,0,0,0,1,
  955.         0,0,1,1,1,1,
  956.         0,0,0,0,0,0,
  957.         /* num: 72 */
  958.         0,1,0,0,0,1,
  959.         0,1,0,0,0,1,
  960.         0,1,0,0,0,1,
  961.         0,1,1,1,1,1,
  962.         0,1,0,0,0,1,
  963.         0,1,0,0,0,1,
  964.         0,1,0,0,0,1,
  965.         0,0,0,0,0,0,
  966.         /* num: 73 */
  967.         0,0,1,1,1,0,
  968.         0,0,0,1,0,0,
  969.         0,0,0,1,0,0,
  970.         0,0,0,1,0,0,
  971.         0,0,0,1,0,0,
  972.         0,0,0,1,0,0,
  973.         0,0,1,1,1,0,
  974.         0,0,0,0,0,0,
  975.         /* num: 74 */
  976.         0,0,0,0,0,1,
  977.         0,0,0,0,0,1,
  978.         0,0,0,0,0,1,
  979.         0,0,0,0,0,1,
  980.         0,1,0,0,0,1,
  981.         0,1,0,0,0,1,
  982.         0,0,1,1,1,0,
  983.         0,0,0,0,0,0,
  984.         /* num: 75 */
  985.         0,1,0,0,0,1,
  986.         0,1,0,0,1,0,
  987.         0,1,0,1,0,0,
  988.         0,1,1,0,0,0,
  989.         0,1,0,1,0,0,
  990.         0,1,0,0,1,0,
  991.         0,1,0,0,0,1,
  992.         0,0,0,0,0,0,
  993.         /* num: 76 */
  994.         0,1,0,0,0,0,
  995.         0,1,0,0,0,0,
  996.         0,1,0,0,0,0,
  997.         0,1,0,0,0,0,
  998.         0,1,0,0,0,0,
  999.         0,1,0,0,0,0,
  1000.         0,1,1,1,1,1,
  1001.         0,0,0,0,0,0,
  1002.         /* num: 77 */
  1003.         0,1,0,0,0,1,
  1004.         0,1,1,0,1,1,
  1005.         0,1,0,1,0,1,
  1006.         0,1,0,0,0,1,
  1007.         0,1,0,0,0,1,
  1008.         0,1,0,0,0,1,
  1009.         0,1,0,0,0,1,
  1010.         0,0,0,0,0,0,
  1011.         /* num: 78 */
  1012.         0,1,0,0,0,1,
  1013.         0,1,1,0,0,1,
  1014.         0,1,0,1,0,1,
  1015.         0,1,0,0,1,1,
  1016.         0,1,0,0,0,1,
  1017.         0,1,0,0,0,1,
  1018.         0,1,0,0,0,1,
  1019.         0,0,0,0,0,0,
  1020.         /* num: 79 */
  1021.         0,0,1,1,1,0,
  1022.         0,1,0,0,0,1,
  1023.         0,1,0,0,0,1,
  1024.         0,1,0,0,0,1,
  1025.         0,1,0,0,0,1,
  1026.         0,1,0,0,0,1,
  1027.         0,0,1,1,1,0,
  1028.         0,0,0,0,0,0,
  1029.         /* num: 80 */
  1030.         0,1,1,1,1,0,
  1031.         0,1,0,0,0,1,
  1032.         0,1,0,0,0,1,
  1033.         0,1,1,1,1,0,
  1034.         0,1,0,0,0,0,
  1035.         0,1,0,0,0,0,
  1036.         0,1,0,0,0,0,
  1037.         0,0,0,0,0,0,
  1038.         /* num: 81 */
  1039.         0,0,1,1,1,0,
  1040.         0,1,0,0,0,1,
  1041.         0,1,0,0,0,1,
  1042.         0,1,0,0,0,1,
  1043.         0,1,0,1,0,1,
  1044.         0,1,0,0,1,0,
  1045.         0,0,1,1,0,1,
  1046.         0,0,0,0,0,0,
  1047.         /* num: 82 */
  1048.         0,1,1,1,1,0,
  1049.         0,1,0,0,0,1,
  1050.         0,1,0,0,0,1,
  1051.         0,1,1,1,1,0,
  1052.         0,1,0,0,1,0,
  1053.         0,1,0,0,0,1,
  1054.         0,1,0,0,0,1,
  1055.         0,0,0,0,0,0,
  1056.         /* num: 83 */
  1057.         0,0,1,1,1,0,
  1058.         0,1,0,0,0,1,
  1059.         0,1,0,0,0,0,
  1060.         0,0,1,1,1,0,
  1061.         0,0,0,0,0,1,
  1062.         0,1,0,0,0,1,
  1063.         0,0,1,1,1,0,
  1064.         0,0,0,0,0,0,
  1065.         /* num: 84 */
  1066.         0,1,1,1,1,1,
  1067.         0,0,0,1,0,0,
  1068.         0,0,0,1,0,0,
  1069.         0,0,0,1,0,0,
  1070.         0,0,0,1,0,0,
  1071.         0,0,0,1,0,0,
  1072.         0,0,0,1,0,0,
  1073.         0,0,0,0,0,0,
  1074.         /* num: 85 */
  1075.         0,1,0,0,0,1,
  1076.         0,1,0,0,0,1,
  1077.         0,1,0,0,0,1,
  1078.         0,1,0,0,0,1,
  1079.         0,1,0,0,0,1,
  1080.         0,1,0,0,0,1,
  1081.         0,0,1,1,1,0,
  1082.         0,0,0,0,0,0,
  1083.         /* num: 86 */
  1084.         0,1,0,0,0,1,
  1085.         0,1,0,0,0,1,
  1086.         0,1,0,0,0,1,
  1087.         0,1,0,0,0,1,
  1088.         0,1,0,0,0,1,
  1089.         0,0,1,0,1,0,
  1090.         0,0,0,1,0,0,
  1091.         0,0,0,0,0,0,
  1092.         /* num: 87 */
  1093.         0,1,0,0,0,1,
  1094.         0,1,0,0,0,1,
  1095.         0,1,0,1,0,1,
  1096.         0,1,0,1,0,1,
  1097.         0,1,0,1,0,1,
  1098.         0,1,0,1,0,1,
  1099.         0,0,1,0,1,0,
  1100.         0,0,0,0,0,0,
  1101.         /* num: 88 */
  1102.         0,1,0,0,0,1,
  1103.         0,1,0,0,0,1,
  1104.         0,0,1,0,1,0,
  1105.         0,0,0,1,0,0,
  1106.         0,0,1,0,1,0,
  1107.         0,1,0,0,0,1,
  1108.         0,1,0,0,0,1,
  1109.         0,0,0,0,0,0,
  1110.         /* num: 89 */
  1111.         0,1,0,0,0,1,
  1112.         0,1,0,0,0,1,
  1113.         0,1,0,0,0,1,
  1114.         0,0,1,0,1,0,
  1115.         0,0,0,1,0,0,
  1116.         0,0,0,1,0,0,
  1117.         0,0,0,1,0,0,
  1118.         0,0,0,0,0,0,
  1119.         /* num: 90 */
  1120.         0,1,1,1,1,0,
  1121.         0,0,0,0,1,0,
  1122.         0,0,0,1,0,0,
  1123.         0,0,1,0,0,0,
  1124.         0,1,0,0,0,0,
  1125.         0,1,0,0,0,0,
  1126.         0,1,1,1,1,0,
  1127.         0,0,0,0,0,0,
  1128.         /* num: 91 */
  1129.         0,0,1,1,1,0,
  1130.         0,0,1,0,0,0,
  1131.         0,0,1,0,0,0,
  1132.         0,0,1,0,0,0,
  1133.         0,0,1,0,0,0,
  1134.         0,0,1,0,0,0,
  1135.         0,0,1,1,1,0,
  1136.         0,0,0,0,0,0,
  1137.         /* num: 92 */
  1138.         0,0,0,0,0,0,
  1139.         0,1,0,0,0,0,
  1140.         0,0,1,0,0,0,
  1141.         0,0,0,1,0,0,
  1142.         0,0,0,0,1,0,
  1143.         0,0,0,0,0,1,
  1144.         0,0,0,0,0,0,
  1145.         0,0,0,0,0,0,
  1146.         /* num: 93 */
  1147.         0,0,1,1,1,0,
  1148.         0,0,0,0,1,0,
  1149.         0,0,0,0,1,0,
  1150.         0,0,0,0,1,0,
  1151.         0,0,0,0,1,0,
  1152.         0,0,0,0,1,0,
  1153.         0,0,1,1,1,0,
  1154.         0,0,0,0,0,0,
  1155.         /* num: 94 */
  1156.         0,0,0,1,0,0,
  1157.         0,0,1,0,1,0,
  1158.         0,1,0,0,0,1,
  1159.         0,0,0,0,0,0,
  1160.         0,0,0,0,0,0,
  1161.         0,0,0,0,0,0,
  1162.         0,0,0,0,0,0,
  1163.         0,0,0,0,0,0,
  1164.         /* num: 95 */
  1165.         0,0,0,0,0,0,
  1166.         0,0,0,0,0,0,
  1167.         0,0,0,0,0,0,
  1168.         0,0,0,0,0,0,
  1169.         0,0,0,0,0,0,
  1170.         0,0,0,0,0,0,
  1171.         0,0,0,0,0,0,
  1172.         1,1,1,1,1,1,
  1173.         /* num: 96 */
  1174.         0,0,1,1,0,0,
  1175.         0,0,1,1,0,0,
  1176.         0,0,0,1,0,0,
  1177.         0,0,0,0,0,0,
  1178.         0,0,0,0,0,0,
  1179.         0,0,0,0,0,0,
  1180.         0,0,0,0,0,0,
  1181.         0,0,0,0,0,0,
  1182.         /* num: 97 */
  1183.         0,0,0,0,0,0,
  1184.         0,0,0,0,0,0,
  1185.         0,0,1,1,1,0,
  1186.         0,0,0,0,0,1,
  1187.         0,0,1,1,1,1,
  1188.         0,1,0,0,0,1,
  1189.         0,0,1,1,1,1,
  1190.         0,0,0,0,0,0,
  1191.         /* num: 98 */
  1192.         0,1,0,0,0,0,
  1193.         0,1,0,0,0,0,
  1194.         0,1,1,1,1,0,
  1195.         0,1,0,0,0,1,
  1196.         0,1,0,0,0,1,
  1197.         0,1,0,0,0,1,
  1198.         0,1,1,1,1,0,
  1199.         0,0,0,0,0,0,
  1200.         /* num: 99 */
  1201.         0,0,0,0,0,0,
  1202.         0,0,0,0,0,0,
  1203.         0,0,1,1,1,0,
  1204.         0,1,0,0,0,1,
  1205.         0,1,0,0,0,0,
  1206.         0,1,0,0,0,1,
  1207.         0,0,1,1,1,0,
  1208.         0,0,0,0,0,0,
  1209.         /* num: 100 */
  1210.         0,0,0,0,0,1,
  1211.         0,0,0,0,0,1,
  1212.         0,0,1,1,1,1,
  1213.         0,1,0,0,0,1,
  1214.         0,1,0,0,0,1,
  1215.         0,1,0,0,0,1,
  1216.         0,0,1,1,1,1,
  1217.         0,0,0,0,0,0,
  1218.         /* num: 101 */
  1219.         0,0,0,0,0,0,
  1220.         0,0,0,0,0,0,
  1221.         0,0,1,1,1,0,
  1222.         0,1,0,0,0,1,
  1223.         0,1,1,1,1,0,
  1224.         0,1,0,0,0,0,
  1225.         0,0,1,1,1,0,
  1226.         0,0,0,0,0,0,
  1227.         /* num: 102 */
  1228.         0,0,0,1,1,0,
  1229.         0,0,1,0,0,0,
  1230.         0,0,1,0,0,0,
  1231.         0,1,1,1,1,0,
  1232.         0,0,1,0,0,0,
  1233.         0,0,1,0,0,0,
  1234.         0,0,1,0,0,0,
  1235.         0,0,0,0,0,0,
  1236.         /* num: 103 */
  1237.         0,0,0,0,0,0,
  1238.         0,0,0,0,0,0,
  1239.         0,0,1,1,1,1,
  1240.         0,1,0,0,0,1,
  1241.         0,1,0,0,0,1,
  1242.         0,0,1,1,1,1,
  1243.         0,0,0,0,0,1,
  1244.         0,0,1,1,1,0,
  1245.         /* num: 104 */
  1246.         0,1,0,0,0,0,
  1247.         0,1,0,0,0,0,
  1248.         0,1,1,1,0,0,
  1249.         0,1,0,0,1,0,
  1250.         0,1,0,0,1,0,
  1251.         0,1,0,0,1,0,
  1252.         0,1,0,0,1,0,
  1253.         0,0,0,0,0,0,
  1254.         /* num: 105 */
  1255.         0,0,0,1,0,0,
  1256.         0,0,0,0,0,0,
  1257.         0,0,0,1,0,0,
  1258.         0,0,0,1,0,0,
  1259.         0,0,0,1,0,0,
  1260.         0,0,0,1,0,0,
  1261.         0,0,0,1,1,0,
  1262.         0,0,0,0,0,0,
  1263.         /* num: 106 */
  1264.         0,0,0,0,1,0,
  1265.         0,0,0,0,0,0,
  1266.         0,0,0,1,1,0,
  1267.         0,0,0,0,1,0,
  1268.         0,0,0,0,1,0,
  1269.         0,0,0,0,1,0,
  1270.         0,1,0,0,1,0,
  1271.         0,0,1,1,0,0,
  1272.         /* num: 107 */
  1273.         0,1,0,0,0,0,
  1274.         0,1,0,0,0,0,
  1275.         0,1,0,0,1,0,
  1276.         0,1,0,1,0,0,
  1277.         0,1,1,0,0,0,
  1278.         0,1,0,1,0,0,
  1279.         0,1,0,0,1,0,
  1280.         0,0,0,0,0,0,
  1281.         /* num: 108 */
  1282.         0,0,0,1,0,0,
  1283.         0,0,0,1,0,0,
  1284.         0,0,0,1,0,0,
  1285.         0,0,0,1,0,0,
  1286.         0,0,0,1,0,0,
  1287.         0,0,0,1,0,0,
  1288.         0,0,0,1,1,0,
  1289.         0,0,0,0,0,0,
  1290.         /* num: 109 */
  1291.         0,0,0,0,0,0,
  1292.         0,0,0,0,0,0,
  1293.         0,1,1,0,1,0,
  1294.         0,1,0,1,0,1,
  1295.         0,1,0,1,0,1,
  1296.         0,1,0,0,0,1,
  1297.         0,1,0,0,0,1,
  1298.         0,0,0,0,0,0,
  1299.         /* num: 110 */
  1300.         0,0,0,0,0,0,
  1301.         0,0,0,0,0,0,
  1302.         0,1,1,1,0,0,
  1303.         0,1,0,0,1,0,
  1304.         0,1,0,0,1,0,
  1305.         0,1,0,0,1,0,
  1306.         0,1,0,0,1,0,
  1307.         0,0,0,0,0,0,
  1308.         /* num: 111 */
  1309.         0,0,0,0,0,0,
  1310.         0,0,0,0,0,0,
  1311.         0,0,1,1,1,0,
  1312.         0,1,0,0,0,1,
  1313.         0,1,0,0,0,1,
  1314.         0,1,0,0,0,1,
  1315.         0,0,1,1,1,0,
  1316.         0,0,0,0,0,0,
  1317.         /* num: 112 */
  1318.         0,0,0,0,0,0,
  1319.         0,0,0,0,0,0,
  1320.         0,1,1,1,1,0,
  1321.         0,1,0,0,0,1,
  1322.         0,1,0,0,0,1,
  1323.         0,1,0,0,0,1,
  1324.         0,1,1,1,1,0,
  1325.         0,1,0,0,0,0,
  1326.         /* num: 113 */
  1327.         0,0,0,0,0,0,
  1328.         0,0,0,0,0,0,
  1329.         0,0,1,1,1,1,
  1330.         0,1,0,0,0,1,
  1331.         0,1,0,0,0,1,
  1332.         0,1,0,0,0,1,
  1333.         0,0,1,1,1,1,
  1334.         0,0,0,0,0,1,
  1335.         /* num: 114 */
  1336.         0,0,0,0,0,0,
  1337.         0,0,0,0,0,0,
  1338.         0,1,0,1,1,0,
  1339.         0,0,1,0,0,1,
  1340.         0,0,1,0,0,0,
  1341.         0,0,1,0,0,0,
  1342.         0,1,1,1,0,0,
  1343.         0,0,0,0,0,0,
  1344.         /* num: 115 */
  1345.         0,0,0,0,0,0,
  1346.         0,0,0,0,0,0,
  1347.         0,0,1,1,1,0,
  1348.         0,1,0,0,0,0,
  1349.         0,0,1,1,1,0,
  1350.         0,0,0,0,0,1,
  1351.         0,0,1,1,1,0,
  1352.         0,0,0,0,0,0,
  1353.         /* num: 116 */
  1354.         0,0,0,0,0,0,
  1355.         0,0,1,0,0,0,
  1356.         0,1,1,1,1,0,
  1357.         0,0,1,0,0,0,
  1358.         0,0,1,0,0,0,
  1359.         0,0,1,0,1,0,
  1360.         0,0,0,1,0,0,
  1361.         0,0,0,0,0,0,
  1362.         /* num: 117 */
  1363.         0,0,0,0,0,0,
  1364.         0,0,0,0,0,0,
  1365.         0,1,0,0,1,0,
  1366.         0,1,0,0,1,0,
  1367.         0,1,0,0,1,0,
  1368.         0,1,0,1,1,0,
  1369.         0,0,1,0,1,0,
  1370.         0,0,0,0,0,0,
  1371.         /* num: 118 */
  1372.         0,0,0,0,0,0,
  1373.         0,0,0,0,0,0,
  1374.         0,1,0,0,0,1,
  1375.         0,1,0,0,0,1,
  1376.         0,1,0,0,0,1,
  1377.         0,0,1,0,1,0,
  1378.         0,0,0,1,0,0,
  1379.         0,0,0,0,0,0,
  1380.         /* num: 119 */
  1381.         0,0,0,0,0,0,
  1382.         0,0,0,0,0,0,
  1383.         0,1,0,0,0,1,
  1384.         0,1,0,0,0,1,
  1385.         0,1,0,1,0,1,
  1386.         0,1,1,1,1,1,
  1387.         0,0,1,0,1,0,
  1388.         0,0,0,0,0,0,
  1389.         /* num: 120 */
  1390.         0,0,0,0,0,0,
  1391.         0,0,0,0,0,0,
  1392.         0,1,0,0,1,0,
  1393.         0,1,0,0,1,0,
  1394.         0,0,1,1,0,0,
  1395.         0,1,0,0,1,0,
  1396.         0,1,0,0,1,0,
  1397.         0,0,0,0,0,0,
  1398.         /* num: 121 */
  1399.         0,0,0,0,0,0,
  1400.         0,0,0,0,0,0,
  1401.         0,1,0,0,1,0,
  1402.         0,1,0,0,1,0,
  1403.         0,1,0,0,1,0,
  1404.         0,0,1,1,1,0,
  1405.         0,0,0,1,0,0,
  1406.         0,1,1,0,0,0,
  1407.         /* num: 122 */
  1408.         0,0,0,0,0,0,
  1409.         0,0,0,0,0,0,
  1410.         0,1,1,1,1,0,
  1411.         0,0,0,0,1,0,
  1412.         0,0,1,1,0,0,
  1413.         0,1,0,0,0,0,
  1414.         0,1,1,1,1,0,
  1415.         0,0,0,0,0,0,
  1416.         /* num: 123 */
  1417.         0,0,0,1,1,0,
  1418.         0,0,1,0,0,0,
  1419.         0,0,1,0,0,0,
  1420.         0,1,1,0,0,0,
  1421.         0,0,1,0,0,0,
  1422.         0,0,1,0,0,0,
  1423.         0,0,0,1,1,0,
  1424.         0,0,0,0,0,0,
  1425.         /* num: 124 */
  1426.         0,0,0,1,0,0,
  1427.         0,0,0,1,0,0,
  1428.         0,0,0,1,0,0,
  1429.         0,0,0,1,0,0,
  1430.         0,0,0,1,0,0,
  1431.         0,0,0,1,0,0,
  1432.         0,0,0,1,0,0,
  1433.         0,0,0,1,0,0,
  1434.         /* num: 125 */
  1435.         0,0,1,1,0,0,
  1436.         0,0,0,0,1,0,
  1437.         0,0,0,0,1,0,
  1438.         0,0,0,0,1,1,
  1439.         0,0,0,0,1,0,
  1440.         0,0,0,0,1,0,
  1441.         0,0,1,1,0,0,
  1442.         0,0,0,0,0,0,
  1443.         /* num: 126 */
  1444.         0,0,1,0,1,0,
  1445.         0,1,0,1,0,0,
  1446.         0,0,0,0,0,0,
  1447.         0,0,0,0,0,0,
  1448.         0,0,0,0,0,0,
  1449.         0,0,0,0,0,0,
  1450.         0,0,0,0,0,0,
  1451.         0,0,0,0,0,0,
  1452.         /* num: 127 */
  1453.         0,0,0,1,0,0,
  1454.         0,0,1,1,1,0,
  1455.         0,1,1,0,1,1,
  1456.         0,1,0,0,0,1,
  1457.         0,1,0,0,0,1,
  1458.         0,1,1,1,1,1,
  1459.         0,0,0,0,0,0,
  1460.         0,0,0,0,0,0,
  1461.         /* num: 128 */
  1462.         0,0,1,1,1,0,
  1463.         0,1,0,0,0,1,
  1464.         0,1,0,0,0,0,
  1465.         0,1,0,0,0,0,
  1466.         0,1,0,0,0,1,
  1467.         0,0,1,1,1,0,
  1468.         0,0,0,1,0,0,
  1469.         0,0,1,1,0,0,
  1470.         /* num: 129 */
  1471.         0,1,0,0,1,0,
  1472.         0,0,0,0,0,0,
  1473.         0,1,0,0,1,0,
  1474.         0,1,0,0,1,0,
  1475.         0,1,0,0,1,0,
  1476.         0,1,0,1,1,0,
  1477.         0,0,1,0,1,0,
  1478.         0,0,0,0,0,0,
  1479.         /* num: 130 */
  1480.         0,0,0,0,1,1,
  1481.         0,0,0,0,0,0,
  1482.         0,0,1,1,1,0,
  1483.         0,1,0,0,0,1,
  1484.         0,1,1,1,1,0,
  1485.         0,1,0,0,0,0,
  1486.         0,0,1,1,1,0,
  1487.         0,0,0,0,0,0,
  1488.         /* num: 131 */
  1489.         0,0,1,1,1,0,
  1490.         0,0,0,0,0,0,
  1491.         0,0,1,1,1,0,
  1492.         0,0,0,0,0,1,
  1493.         0,0,1,1,1,1,
  1494.         0,1,0,0,0,1,
  1495.         0,0,1,1,1,1,
  1496.         0,0,0,0,0,0,
  1497.         /* num: 132 */
  1498.         0,0,1,0,1,0,
  1499.         0,0,0,0,0,0,
  1500.         0,0,1,1,1,0,
  1501.         0,0,0,0,0,1,
  1502.         0,0,1,1,1,1,
  1503.         0,1,0,0,0,1,
  1504.         0,0,1,1,1,1,
  1505.         0,0,0,0,0,0,
  1506.         /* num: 133 */
  1507.         0,0,1,1,0,0,
  1508.         0,0,0,0,0,0,
  1509.         0,0,1,1,1,0,
  1510.         0,0,0,0,0,1,
  1511.         0,0,1,1,1,1,
  1512.         0,1,0,0,0,1,
  1513.         0,0,1,1,1,1,
  1514.         0,0,0,0,0,0,
  1515.         /* num: 134 */
  1516.         0,0,1,1,1,0,
  1517.         0,0,1,0,1,0,
  1518.         0,0,1,1,1,0,
  1519.         0,0,0,0,0,1,
  1520.         0,0,1,1,1,1,
  1521.         0,1,0,0,0,1,
  1522.         0,0,1,1,1,1,
  1523.         0,0,0,0,0,0,
  1524.         /* num: 135 */
  1525.         0,0,0,0,0,0,
  1526.         0,0,1,1,1,0,
  1527.         0,1,0,0,0,1,
  1528.         0,1,0,0,0,0,
  1529.         0,1,0,0,0,1,
  1530.         0,0,1,1,1,0,
  1531.         0,0,0,1,0,0,
  1532.         0,0,1,1,0,0,
  1533.         /* num: 136 */
  1534.         0,0,1,1,1,0,
  1535.         0,0,0,0,0,0,
  1536.         0,0,1,1,1,0,
  1537.         0,1,0,0,0,1,
  1538.         0,1,1,1,1,0,
  1539.         0,1,0,0,0,0,
  1540.         0,0,1,1,1,0,
  1541.         0,0,0,0,0,0,
  1542.         /* num: 137 */
  1543.         0,0,1,0,1,0,
  1544.         0,0,0,0,0,0,
  1545.         0,0,1,1,1,0,
  1546.         0,1,0,0,0,1,
  1547.         0,1,1,1,1,0,
  1548.         0,1,0,0,0,0,
  1549.         0,0,1,1,1,0,
  1550.         0,0,0,0,0,0,
  1551.         /* num: 138 */
  1552.         0,0,1,1,0,0,
  1553.         0,0,0,0,0,0,
  1554.         0,0,1,1,1,0,
  1555.         0,1,0,0,0,1,
  1556.         0,1,1,1,1,0,
  1557.         0,1,0,0,0,0,
  1558.         0,0,1,1,1,0,
  1559.         0,0,0,0,0,0,
  1560.         /* num: 139 */
  1561.         0,0,1,0,1,0,
  1562.         0,0,0,0,0,0,
  1563.         0,0,0,1,0,0,
  1564.         0,0,0,1,0,0,
  1565.         0,0,0,1,0,0,
  1566.         0,0,0,1,0,0,
  1567.         0,0,0,1,1,0,
  1568.         0,0,0,0,0,0,
  1569.         /* num: 140 */
  1570.         0,0,0,1,0,0,
  1571.         0,0,1,0,1,0,
  1572.         0,0,0,0,0,0,
  1573.         0,0,0,1,0,0,
  1574.         0,0,0,1,0,0,
  1575.         0,0,0,1,0,0,
  1576.         0,0,0,1,1,0,
  1577.         0,0,0,0,0,0,
  1578.         /* num: 141 */
  1579.         0,0,1,0,0,0,
  1580.         0,0,0,0,0,0,
  1581.         0,0,0,1,0,0,
  1582.         0,0,0,1,0,0,
  1583.         0,0,0,1,0,0,
  1584.         0,0,0,1,0,0,
  1585.         0,0,0,1,1,0,
  1586.         0,0,0,0,0,0,
  1587.         /* num: 142 */
  1588.         0,0,1,0,1,0,
  1589.         0,0,0,0,0,0,
  1590.         0,0,0,1,0,0,
  1591.         0,0,1,0,1,0,
  1592.         0,1,0,0,0,1,
  1593.         0,1,1,1,1,1,
  1594.         0,1,0,0,0,1,
  1595.         0,0,0,0,0,0,
  1596.         /* num: 143 */
  1597.         0,0,1,1,1,0,
  1598.         0,0,1,0,1,0,
  1599.         0,0,1,1,1,0,
  1600.         0,1,1,0,1,1,
  1601.         0,1,0,0,0,1,
  1602.         0,1,1,1,1,1,
  1603.         0,1,0,0,0,1,
  1604.         0,0,0,0,0,0,
  1605.         /* num: 144 */
  1606.         0,0,0,0,1,1,
  1607.         0,0,0,0,0,0,
  1608.         0,1,1,1,1,1,
  1609.         0,1,0,0,0,0,
  1610.         0,1,1,1,1,0,
  1611.         0,1,0,0,0,0,
  1612.         0,1,1,1,1,1,
  1613.         0,0,0,0,0,0,
  1614.         /* num: 145 */
  1615.         0,0,0,0,0,0,
  1616.         0,0,0,0,0,0,
  1617.         0,1,1,1,1,0,
  1618.         0,0,0,1,0,1,
  1619.         0,1,1,1,1,1,
  1620.         0,1,0,1,0,0,
  1621.         0,0,1,1,1,1,
  1622.         0,0,0,0,0,0,
  1623.         /* num: 146 */
  1624.         0,0,1,1,1,1,
  1625.         0,1,0,1,0,0,
  1626.         0,1,0,1,0,0,
  1627.         0,1,1,1,1,1,
  1628.         0,1,0,1,0,0,
  1629.         0,1,0,1,0,0,
  1630.         0,1,0,1,1,1,
  1631.         0,0,0,0,0,0,
  1632.         /* num: 147 */
  1633.         0,0,1,1,1,0,
  1634.         0,0,0,0,0,0,
  1635.         0,0,1,1,0,0,
  1636.         0,1,0,0,1,0,
  1637.         0,1,0,0,1,0,
  1638.         0,1,0,0,1,0,
  1639.         0,0,1,1,0,0,
  1640.         0,0,0,0,0,0,
  1641.         /* num: 148 */
  1642.         0,0,1,0,1,0,
  1643.         0,0,0,0,0,0,
  1644.         0,0,1,1,0,0,
  1645.         0,1,0,0,1,0,
  1646.         0,1,0,0,1,0,
  1647.         0,1,0,0,1,0,
  1648.         0,0,1,1,0,0,
  1649.         0,0,0,0,0,0,
  1650.         /* num: 149 */
  1651.         0,1,1,0,0,0,
  1652.         0,0,0,0,0,0,
  1653.         0,0,1,1,0,0,
  1654.         0,1,0,0,1,0,
  1655.         0,1,0,0,1,0,
  1656.         0,1,0,0,1,0,
  1657.         0,0,1,1,0,0,
  1658.         0,0,0,0,0,0,
  1659.         /* num: 150 */
  1660.         0,0,1,1,1,0,
  1661.         0,0,0,0,0,0,
  1662.         0,1,0,0,1,0,
  1663.         0,1,0,0,1,0,
  1664.         0,1,0,0,1,0,
  1665.         0,1,0,1,1,0,
  1666.         0,0,1,0,1,0,
  1667.         0,0,0,0,0,0,
  1668.         /* num: 151 */
  1669.         0,1,1,0,0,0,
  1670.         0,0,0,0,0,0,
  1671.         0,1,0,0,1,0,
  1672.         0,1,0,0,1,0,
  1673.         0,1,0,0,1,0,
  1674.         0,1,0,1,1,0,
  1675.         0,0,1,0,1,0,
  1676.         0,0,0,0,0,0,
  1677.         /* num: 152 */
  1678.         0,0,1,0,1,0,
  1679.         0,0,0,0,0,0,
  1680.         0,1,0,0,1,0,
  1681.         0,1,0,0,1,0,
  1682.         0,1,0,0,1,0,
  1683.         0,0,1,1,1,0,
  1684.         0,0,0,1,0,0,
  1685.         0,1,1,0,0,0,
  1686.         /* num: 153 */
  1687.         0,1,0,0,1,0,
  1688.         0,0,1,1,0,0,
  1689.         0,1,0,0,1,0,
  1690.         0,1,0,0,1,0,
  1691.         0,1,0,0,1,0,
  1692.         0,1,0,0,1,0,
  1693.         0,0,1,1,0,0,
  1694.         0,0,0,0,0,0,
  1695.         /* num: 154 */
  1696.         0,0,1,0,1,0,
  1697.         0,0,0,0,0,0,
  1698.         0,1,0,0,1,0,
  1699.         0,1,0,0,1,0,
  1700.         0,1,0,0,1,0,
  1701.         0,1,0,0,1,0,
  1702.         0,0,1,1,0,0,
  1703.         0,0,0,0,0,0,
  1704.         /* num: 155 */
  1705.         0,0,0,0,0,0,
  1706.         0,0,0,1,0,0,
  1707.         0,0,1,1,1,0,
  1708.         0,1,0,0,0,0,
  1709.         0,1,0,0,0,0,
  1710.         0,0,1,1,1,0,
  1711.         0,0,0,1,0,0,
  1712.         0,0,0,0,0,0,
  1713.         /* num: 156 */
  1714.         0,0,0,1,1,0,
  1715.         0,0,1,0,0,1,
  1716.         0,0,1,0,0,0,
  1717.         0,1,1,1,1,0,
  1718.         0,0,1,0,0,0,
  1719.         0,0,1,0,0,1,
  1720.         0,1,0,1,1,1,
  1721.         0,0,0,0,0,0,
  1722.         /* num: 157 */
  1723.         0,1,0,0,0,1,
  1724.         0,0,1,0,1,0,
  1725.         0,0,0,1,0,0,
  1726.         0,1,1,1,1,1,
  1727.         0,0,0,1,0,0,
  1728.         0,1,1,1,1,1,
  1729.         0,0,0,1,0,0,
  1730.         0,0,0,0,0,0,
  1731.         /* num: 158 */
  1732.         0,1,1,0,0,0,
  1733.         0,1,0,1,0,0,
  1734.         0,1,0,1,0,0,
  1735.         0,1,1,0,1,0,
  1736.         0,1,0,1,1,1,
  1737.         0,1,0,0,1,0,
  1738.         0,1,0,0,1,0,
  1739.         0,0,0,0,0,0,
  1740.         /* num: 159 */
  1741.         0,0,0,0,1,0,
  1742.         0,0,0,1,0,1,
  1743.         0,0,0,1,0,0,
  1744.         0,0,1,1,1,0,
  1745.         0,0,0,1,0,0,
  1746.         0,0,0,1,0,0,
  1747.         0,1,0,1,0,0,
  1748.         0,0,1,0,0,0,
  1749.         /* num: 160 */
  1750.         0,0,0,1,1,0,
  1751.         0,0,0,0,0,0,
  1752.         0,0,1,1,1,0,
  1753.         0,0,0,0,0,1,
  1754.         0,0,1,1,1,1,
  1755.         0,1,0,0,0,1,
  1756.         0,0,1,1,1,1,
  1757.         0,0,0,0,0,0,
  1758.         /* num: 161 */
  1759.         0,0,0,1,1,0,
  1760.         0,0,0,0,0,0,
  1761.         0,0,0,1,0,0,
  1762.         0,0,0,1,0,0,
  1763.         0,0,0,1,0,0,
  1764.         0,0,0,1,0,0,
  1765.         0,0,0,1,1,0,
  1766.         0,0,0,0,0,0,
  1767.         /* num: 162 */
  1768.         0,0,0,1,1,0,
  1769.         0,0,0,0,0,0,
  1770.         0,0,1,1,0,0,
  1771.         0,1,0,0,1,0,
  1772.         0,1,0,0,1,0,
  1773.         0,1,0,0,1,0,
  1774.         0,0,1,1,0,0,
  1775.         0,0,0,0,0,0,
  1776.         /* num: 163 */
  1777.         0,0,0,1,1,0,
  1778.         0,0,0,0,0,0,
  1779.         0,1,0,0,1,0,
  1780.         0,1,0,0,1,0,
  1781.         0,1,0,0,1,0,
  1782.         0,1,0,1,1,0,
  1783.         0,0,1,0,1,0,
  1784.         0,0,0,0,0,0,
  1785.         /* num: 164 */
  1786.         0,0,1,0,1,0,
  1787.         0,1,0,1,0,0,
  1788.         0,0,0,0,0,0,
  1789.         0,1,1,1,0,0,
  1790.         0,1,0,0,1,0,
  1791.         0,1,0,0,1,0,
  1792.         0,1,0,0,1,0,
  1793.         0,0,0,0,0,0,
  1794.         /* num: 165 */
  1795.         0,0,1,0,1,0,
  1796.         0,1,0,1,0,0,
  1797.         0,0,0,0,0,0,
  1798.         0,1,0,0,1,0,
  1799.         0,1,1,0,1,0,
  1800.         0,1,0,1,1,0,
  1801.         0,1,0,0,1,0,
  1802.         0,0,0,0,0,0,
  1803.         /* num: 166 */
  1804.         0,0,1,1,1,0,
  1805.         0,0,0,0,0,1,
  1806.         0,0,1,1,1,1,
  1807.         0,1,0,0,0,1,
  1808.         0,0,1,1,1,1,
  1809.         0,0,0,0,0,0,
  1810.         0,0,1,1,1,1,
  1811.         0,0,0,0,0,0,
  1812.         /* num: 167 */
  1813.         0,0,1,1,0,0,
  1814.         0,1,0,0,1,0,
  1815.         0,1,0,0,1,0,
  1816.         0,1,0,0,1,0,
  1817.         0,0,1,1,0,0,
  1818.         0,0,0,0,0,0,
  1819.         0,1,1,1,1,0,
  1820.         0,0,0,0,0,0,
  1821.         /* num: 168 */
  1822.         0,0,0,1,0,0,
  1823.         0,0,0,0,0,0,
  1824.         0,0,0,1,0,0,
  1825.         0,0,1,1,0,0,
  1826.         0,1,0,0,0,0,
  1827.         0,1,0,0,0,1,
  1828.         0,0,1,1,1,0,
  1829.         0,0,0,0,0,0,
  1830.         /* num: 169 */
  1831.         0,0,0,0,0,0,
  1832.         0,0,0,0,0,0,
  1833.         0,1,1,1,1,1,
  1834.         0,1,0,0,0,0,
  1835.         0,1,0,0,0,0,
  1836.         0,1,0,0,0,0,
  1837.         0,0,0,0,0,0,
  1838.         0,0,0,0,0,0,
  1839.         /* num: 170 */
  1840.         0,0,0,0,0,0,
  1841.         0,0,0,0,0,0,
  1842.         1,1,1,1,1,1,
  1843.         0,0,0,0,0,1,
  1844.         0,0,0,0,0,1,
  1845.         0,0,0,0,0,0,
  1846.         0,0,0,0,0,0,
  1847.         0,0,0,0,0,0,
  1848.         /* num: 171 */
  1849.         0,1,0,0,0,0,
  1850.         0,1,0,0,1,0,
  1851.         0,1,0,1,0,0,
  1852.         0,0,1,1,1,0,
  1853.         0,1,0,0,0,1,
  1854.         0,0,0,0,1,0,
  1855.         0,0,0,1,1,1,
  1856.         0,0,0,0,0,0,
  1857.         /* num: 172 */
  1858.         0,1,0,0,0,0,
  1859.         0,1,0,0,1,0,
  1860.         0,1,0,1,0,0,
  1861.         0,0,1,0,1,1,
  1862.         0,1,0,1,0,1,
  1863.         0,0,0,1,1,1,
  1864.         0,0,0,0,0,1,
  1865.         0,0,0,0,0,0,
  1866.         /* num: 173 */
  1867.         0,0,0,1,0,0,
  1868.         0,0,0,0,0,0,
  1869.         0,0,0,1,0,0,
  1870.         0,0,0,1,0,0,
  1871.         0,0,1,1,1,0,
  1872.         0,0,1,1,1,0,
  1873.         0,0,0,1,0,0,
  1874.         0,0,0,0,0,0,
  1875.         /* num: 174 */
  1876.         0,0,0,0,0,0,
  1877.         0,0,0,0,0,0,
  1878.         0,0,1,0,0,1,
  1879.         0,1,0,0,1,0,
  1880.         0,0,1,0,0,1,
  1881.         0,0,0,0,0,0,
  1882.         0,0,0,0,0,0,
  1883.         0,0,0,0,0,0,
  1884.         /* num: 175 */
  1885.         0,0,0,0,0,0,
  1886.         0,0,0,0,0,0,
  1887.         0,1,0,0,1,0,
  1888.         0,0,1,0,0,1,
  1889.         0,1,0,0,1,0,
  1890.         0,0,0,0,0,0,
  1891.         0,0,0,0,0,0,
  1892.         0,0,0,0,0,0,
  1893.         /* num: 176 */
  1894.         0,1,0,1,0,1,
  1895.         0,0,0,0,0,0,
  1896.         1,0,1,0,1,0,
  1897.         0,0,0,0,0,0,
  1898.         0,1,0,1,0,1,
  1899.         0,0,0,0,0,0,
  1900.         1,0,1,0,1,0,
  1901.         0,0,0,0,0,0,
  1902.         /* num: 177 */
  1903.         0,1,0,1,0,1,
  1904.         1,0,1,0,1,0,
  1905.         0,1,0,1,0,1,
  1906.         1,0,1,0,1,0,
  1907.         0,1,0,1,0,1,
  1908.         1,0,1,0,1,0,
  1909.         0,1,0,1,0,1,
  1910.         1,0,1,0,1,0,
  1911.         /* num: 178 */
  1912.         1,0,1,0,1,0,
  1913.         1,1,1,1,1,1,
  1914.         0,1,0,1,0,1,
  1915.         1,1,1,1,1,1,
  1916.         1,0,1,0,1,0,
  1917.         1,1,1,1,1,1,
  1918.         0,1,0,1,0,1,
  1919.         1,1,1,1,1,1,
  1920.         /* num: 179 */
  1921.         0,0,0,1,0,0,
  1922.         0,0,0,1,0,0,
  1923.         0,0,0,1,0,0,
  1924.         0,0,0,1,0,0,
  1925.         0,0,0,1,0,0,
  1926.         0,0,0,1,0,0,
  1927.         0,0,0,1,0,0,
  1928.         0,0,0,1,0,0,
  1929.         /* num: 180 */
  1930.         0,0,0,1,0,0,
  1931.         0,0,0,1,0,0,
  1932.         0,0,0,1,0,0,
  1933.         1,1,1,1,0,0,
  1934.         0,0,0,1,0,0,
  1935.         0,0,0,1,0,0,
  1936.         0,0,0,1,0,0,
  1937.         0,0,0,1,0,0,
  1938.         /* num: 181 */
  1939.         0,0,0,0,0,0,
  1940.         0,0,0,0,0,0,
  1941.         0,1,0,0,1,0,
  1942.         0,1,0,0,1,0,
  1943.         0,1,0,0,1,0,
  1944.         0,1,1,1,0,0,
  1945.         0,1,0,0,0,0,
  1946.         0,1,0,0,0,0,
  1947.         /* num: 182 */
  1948.         0,1,0,1,0,0,
  1949.         0,1,0,1,0,0,
  1950.         0,1,0,1,0,0,
  1951.         1,1,0,1,0,0,
  1952.         0,1,0,1,0,0,
  1953.         0,1,0,1,0,0,
  1954.         0,1,0,1,0,0,
  1955.         0,1,0,1,0,0,
  1956.         /* num: 183 */
  1957.         0,0,0,0,0,0,
  1958.         0,0,0,0,0,0,
  1959.         0,0,0,0,0,0,
  1960.         1,1,1,1,0,0,
  1961.         0,1,0,1,0,0,
  1962.         0,1,0,1,0,0,
  1963.         0,1,0,1,0,0,
  1964.         0,1,0,1,0,0,
  1965.         /* num: 184 */
  1966.         0,0,0,0,0,0,
  1967.         1,1,1,1,0,0,
  1968.         0,0,0,1,0,0,
  1969.         1,1,1,1,0,0,
  1970.         0,0,0,1,0,0,
  1971.         0,0,0,1,0,0,
  1972.         0,0,0,1,0,0,
  1973.         0,0,0,1,0,0,
  1974.         /* num: 185 */
  1975.         0,1,0,1,0,0,
  1976.         1,1,0,1,0,0,
  1977.         0,0,0,1,0,0,
  1978.         1,1,0,1,0,0,
  1979.         0,1,0,1,0,0,
  1980.         0,1,0,1,0,0,
  1981.         0,1,0,1,0,0,
  1982.         0,1,0,1,0,0,
  1983.         /* num: 186 */
  1984.         0,1,0,1,0,0,
  1985.         0,1,0,1,0,0,
  1986.         0,1,0,1,0,0,
  1987.         0,1,0,1,0,0,
  1988.         0,1,0,1,0,0,
  1989.         0,1,0,1,0,0,
  1990.         0,1,0,1,0,0,
  1991.         0,1,0,1,0,0,
  1992.         /* num: 187 */
  1993.         0,0,0,0,0,0,
  1994.         1,1,1,1,0,0,
  1995.         0,0,0,1,0,0,
  1996.         1,1,0,1,0,0,
  1997.         0,1,0,1,0,0,
  1998.         0,1,0,1,0,0,
  1999.         0,1,0,1,0,0,
  2000.         0,1,0,1,0,0,
  2001.         /* num: 188 */
  2002.         0,1,0,1,0,0,
  2003.         1,1,0,1,0,0,
  2004.         0,0,0,1,0,0,
  2005.         1,1,1,1,0,0,
  2006.         0,0,0,0,0,0,
  2007.         0,0,0,0,0,0,
  2008.         0,0,0,0,0,0,
  2009.         0,0,0,0,0,0,
  2010.         /* num: 189 */
  2011.         0,1,0,1,0,0,
  2012.         0,1,0,1,0,0,
  2013.         0,1,0,1,0,0,
  2014.         1,1,1,1,0,0,
  2015.         0,0,0,0,0,0,
  2016.         0,0,0,0,0,0,
  2017.         0,0,0,0,0,0,
  2018.         0,0,0,0,0,0,
  2019.         /* num: 190 */
  2020.         0,0,0,1,0,0,
  2021.         1,1,1,1,0,0,
  2022.         0,0,0,1,0,0,
  2023.         1,1,1,1,0,0,
  2024.         0,0,0,0,0,0,
  2025.         0,0,0,0,0,0,
  2026.         0,0,0,0,0,0,
  2027.         0,0,0,0,0,0,
  2028.         /* num: 191 */
  2029.         0,0,0,0,0,0,
  2030.         0,0,0,0,0,0,
  2031.         0,0,0,0,0,0,
  2032.         1,1,1,1,0,0,
  2033.         0,0,0,1,0,0,
  2034.         0,0,0,1,0,0,
  2035.         0,0,0,1,0,0,
  2036.         0,0,0,1,0,0,
  2037.         /* num: 192 */
  2038.         0,0,0,1,0,0,
  2039.         0,0,0,1,0,0,
  2040.         0,0,0,1,0,0,
  2041.         0,0,0,1,1,1,
  2042.         0,0,0,0,0,0,
  2043.         0,0,0,0,0,0,
  2044.         0,0,0,0,0,0,
  2045.         0,0,0,0,0,0,
  2046.         /* num: 193 */
  2047.         0,0,0,1,0,0,
  2048.         0,0,0,1,0,0,
  2049.         0,0,0,1,0,0,
  2050.         1,1,1,1,1,1,
  2051.         0,0,0,0,0,0,
  2052.         0,0,0,0,0,0,
  2053.         0,0,0,0,0,0,
  2054.         0,0,0,0,0,0,
  2055.         /* num: 194 */
  2056.         0,0,0,0,0,0,
  2057.         0,0,0,0,0,0,
  2058.         0,0,0,0,0,0,
  2059.         1,1,1,1,1,1,
  2060.         0,0,0,1,0,0,
  2061.         0,0,0,1,0,0,
  2062.         0,0,0,1,0,0,
  2063.         0,0,0,1,0,0,
  2064.         /* num: 195 */
  2065.         0,0,0,1,0,0,
  2066.         0,0,0,1,0,0,
  2067.         0,0,0,1,0,0,
  2068.         0,0,0,1,1,1,
  2069.         0,0,0,1,0,0,
  2070.         0,0,0,1,0,0,
  2071.         0,0,0,1,0,0,
  2072.         0,0,0,1,0,0,
  2073.         /* num: 196 */
  2074.         0,0,0,0,0,0,
  2075.         0,0,0,0,0,0,
  2076.         0,0,0,0,0,0,
  2077.         1,1,1,1,1,1,
  2078.         0,0,0,0,0,0,
  2079.         0,0,0,0,0,0,
  2080.         0,0,0,0,0,0,
  2081.         0,0,0,0,0,0,
  2082.         /* num: 197 */
  2083.         0,0,0,1,0,0,
  2084.         0,0,0,1,0,0,
  2085.         0,0,0,1,0,0,
  2086.         1,1,1,1,1,1,
  2087.         0,0,0,1,0,0,
  2088.         0,0,0,1,0,0,
  2089.         0,0,0,1,0,0,
  2090.         0,0,0,1,0,0,
  2091.         /* num: 198 */
  2092.         0,0,0,1,0,0,
  2093.         0,0,0,1,1,1,
  2094.         0,0,0,1,0,0,
  2095.         0,0,0,1,1,1,
  2096.         0,0,0,1,0,0,
  2097.         0,0,0,1,0,0,
  2098.         0,0,0,1,0,0,
  2099.         0,0,0,1,0,0,
  2100.         /* num: 199 */
  2101.         0,1,0,1,0,0,
  2102.         0,1,0,1,0,0,
  2103.         0,1,0,1,0,0,
  2104.         0,1,0,1,1,1,
  2105.         0,1,0,1,0,0,
  2106.         0,1,0,1,0,0,
  2107.         0,1,0,1,0,0,
  2108.         0,1,0,1,0,0,
  2109.         /* num: 200 */
  2110.         0,1,0,1,0,0,
  2111.         0,1,0,1,1,1,
  2112.         0,1,0,0,0,0,
  2113.         0,1,1,1,1,1,
  2114.         0,0,0,0,0,0,
  2115.         0,0,0,0,0,0,
  2116.         0,0,0,0,0,0,
  2117.         0,0,0,0,0,0,
  2118.         /* num: 201 */
  2119.         0,0,0,0,0,0,
  2120.         0,1,1,1,1,1,
  2121.         0,1,0,0,0,0,
  2122.         0,1,0,1,1,1,
  2123.         0,1,0,1,0,0,
  2124.         0,1,0,1,0,0,
  2125.         0,1,0,1,0,0,
  2126.         0,1,0,1,0,0,
  2127.         /* num: 202 */
  2128.         0,1,0,1,0,0,
  2129.         1,1,0,1,1,1,
  2130.         0,0,0,0,0,0,
  2131.         1,1,1,1,1,1,
  2132.         0,0,0,0,0,0,
  2133.         0,0,0,0,0,0,
  2134.         0,0,0,0,0,0,
  2135.         0,0,0,0,0,0,
  2136.         /* num: 203 */
  2137.         0,0,0,0,0,0,
  2138.         1,1,1,1,1,1,
  2139.         0,0,0,0,0,0,
  2140.         1,1,0,1,1,1,
  2141.         0,1,0,1,0,0,
  2142.         0,1,0,1,0,0,
  2143.         0,1,0,1,0,0,
  2144.         0,1,0,1,0,0,
  2145.         /* num: 204 */
  2146.         0,1,0,1,0,0,
  2147.         0,1,0,1,1,1,
  2148.         0,1,0,0,0,0,
  2149.         0,1,0,1,1,1,
  2150.         0,1,0,1,0,0,
  2151.         0,1,0,1,0,0,
  2152.         0,1,0,1,0,0,
  2153.         0,1,0,1,0,0,
  2154.         /* num: 205 */
  2155.         0,0,0,0,0,0,
  2156.         1,1,1,1,1,1,
  2157.         0,0,0,0,0,0,
  2158.         1,1,1,1,1,1,
  2159.         0,0,0,0,0,0,
  2160.         0,0,0,0,0,0,
  2161.         0,0,0,0,0,0,
  2162.         0,0,0,0,0,0,
  2163.         /* num: 206 */
  2164.         0,1,0,1,0,0,
  2165.         1,1,0,1,1,1,
  2166.         0,0,0,0,0,0,
  2167.         1,1,0,1,1,1,
  2168.         0,1,0,1,0,0,
  2169.         0,1,0,1,0,0,
  2170.         0,1,0,1,0,0,
  2171.         0,1,0,1,0,0,
  2172.         /* num: 207 */
  2173.         0,0,0,1,0,0,
  2174.         1,1,1,1,1,1,
  2175.         0,0,0,0,0,0,
  2176.         1,1,1,1,1,1,
  2177.         0,0,0,0,0,0,
  2178.         0,0,0,0,0,0,
  2179.         0,0,0,0,0,0,
  2180.         0,0,0,0,0,0,
  2181.         /* num: 208 */
  2182.         0,1,0,1,0,0,
  2183.         0,1,0,1,0,0,
  2184.         0,1,0,1,0,0,
  2185.         1,1,1,1,1,1,
  2186.         0,0,0,0,0,0,
  2187.         0,0,0,0,0,0,
  2188.         0,0,0,0,0,0,
  2189.         0,0,0,0,0,0,
  2190.         /* num: 209 */
  2191.         0,0,0,0,0,0,
  2192.         1,1,1,1,1,1,
  2193.         0,0,0,0,0,0,
  2194.         1,1,1,1,1,1,
  2195.         0,0,0,1,0,0,
  2196.         0,0,0,1,0,0,
  2197.         0,0,0,1,0,0,
  2198.         0,0,0,1,0,0,
  2199.         /* num: 210 */
  2200.         0,0,0,0,0,0,
  2201.         0,0,0,0,0,0,
  2202.         0,0,0,0,0,0,
  2203.         1,1,1,1,1,1,
  2204.         0,1,0,1,0,0,
  2205.         0,1,0,1,0,0,
  2206.         0,1,0,1,0,0,
  2207.         0,1,0,1,0,0,
  2208.         /* num: 211 */
  2209.         0,1,0,1,0,0,
  2210.         0,1,0,1,0,0,
  2211.         0,1,0,1,0,0,
  2212.         0,1,1,1,1,1,
  2213.         0,0,0,0,0,0,
  2214.         0,0,0,0,0,0,
  2215.         0,0,0,0,0,0,
  2216.         0,0,0,0,0,0,
  2217.         /* num: 212 */
  2218.         0,0,0,0,0,0,
  2219.         0,0,0,0,0,0,
  2220.         0,0,0,0,0,0,
  2221.         0,0,0,0,0,0,
  2222.         0,0,0,0,0,0,
  2223.         0,0,0,0,0,0,
  2224.         0,0,0,0,0,0,
  2225.         1,1,1,1,1,1,
  2226.         /* num: 213 */
  2227.         0,0,0,0,0,0,
  2228.         0,0,0,0,0,0,
  2229.         0,0,0,0,0,0,
  2230.         0,0,0,0,0,0,
  2231.         0,0,0,0,0,0,
  2232.         0,0,0,0,0,0,
  2233.         1,1,1,1,1,1,
  2234.         1,1,1,1,1,1,
  2235.         /* num: 214 */
  2236.         0,0,0,0,0,0,
  2237.         0,0,0,0,0,0,
  2238.         0,0,0,0,0,0,
  2239.         0,0,0,0,0,0,
  2240.         0,0,0,0,0,0,
  2241.         1,1,1,1,1,1,
  2242.         1,1,1,1,1,1,
  2243.         1,1,1,1,1,1,
  2244.         /* num: 215 */
  2245.         0,0,0,0,0,0,
  2246.         0,0,0,0,0,0,
  2247.         0,0,0,0,0,0,
  2248.         0,0,0,0,0,0,
  2249.         1,1,1,1,1,1,
  2250.         1,1,1,1,1,1,
  2251.         1,1,1,1,1,1,
  2252.         1,1,1,1,1,1,
  2253.         /* num: 216 */
  2254.         0,0,0,0,0,0,
  2255.         0,0,0,0,0,0,
  2256.         0,0,0,0,0,0,
  2257.         1,1,1,1,1,1,
  2258.         1,1,1,1,1,1,
  2259.         1,1,1,1,1,1,
  2260.         1,1,1,1,1,1,
  2261.         1,1,1,1,1,1,
  2262.         /* num: 217 */
  2263.         0,0,0,0,0,0,
  2264.         0,0,0,0,0,0,
  2265.         1,1,1,1,1,1,
  2266.         1,1,1,1,1,1,
  2267.         1,1,1,1,1,1,
  2268.         1,1,1,1,1,1,
  2269.         1,1,1,1,1,1,
  2270.         1,1,1,1,1,1,
  2271.         /* num: 218 */
  2272.         0,0,0,0,0,0,
  2273.         1,1,1,1,1,1,
  2274.         1,1,1,1,1,1,
  2275.         1,1,1,1,1,1,
  2276.         1,1,1,1,1,1,
  2277.         1,1,1,1,1,1,
  2278.         1,1,1,1,1,1,
  2279.         1,1,1,1,1,1,
  2280.         /* num: 219 */
  2281.         1,1,1,1,1,1,
  2282.         1,1,1,1,1,1,
  2283.         1,1,1,1,1,1,
  2284.         1,1,1,1,1,1,
  2285.         1,1,1,1,1,1,
  2286.         1,1,1,1,1,1,
  2287.         1,1,1,1,1,1,
  2288.         1,1,1,1,1,1,
  2289.         /* num: 220 */
  2290.         1,0,0,0,0,0,
  2291.         1,0,0,0,0,0,
  2292.         1,0,0,0,0,0,
  2293.         1,0,0,0,0,0,
  2294.         1,0,0,0,0,0,
  2295.         1,0,0,0,0,0,
  2296.         1,0,0,0,0,0,
  2297.         1,0,0,0,0,0,
  2298.         /* num: 221 */
  2299.         1,1,0,0,0,0,
  2300.         1,1,0,0,0,0,
  2301.         1,1,0,0,0,0,
  2302.         1,1,0,0,0,0,
  2303.         1,1,0,0,0,0,
  2304.         1,1,0,0,0,0,
  2305.         1,1,0,0,0,0,
  2306.         1,1,0,0,0,0,
  2307.         /* num: 222 */
  2308.         1,1,1,0,0,0,
  2309.         1,1,1,0,0,0,
  2310.         1,1,1,0,0,0,
  2311.         1,1,1,0,0,0,
  2312.         1,1,1,0,0,0,
  2313.         1,1,1,0,0,0,
  2314.         1,1,1,0,0,0,
  2315.         1,1,1,0,0,0,
  2316.         /* num: 223 */
  2317.         1,1,1,1,0,0,
  2318.         1,1,1,1,0,0,
  2319.         1,1,1,1,0,0,
  2320.         1,1,1,1,0,0,
  2321.         1,1,1,1,0,0,
  2322.         1,1,1,1,0,0,
  2323.         1,1,1,1,0,0,
  2324.         1,1,1,1,0,0,
  2325.         /* num: 224 */
  2326.         1,1,1,1,1,0,
  2327.         1,1,1,1,1,0,
  2328.         1,1,1,1,1,0,
  2329.         1,1,1,1,1,0,
  2330.         1,1,1,1,1,0,
  2331.         1,1,1,1,1,0,
  2332.         1,1,1,1,1,0,
  2333.         1,1,1,1,1,0,
  2334.         /* num: 225 */
  2335.         0,0,0,0,0,0,
  2336.         0,1,1,1,0,0,
  2337.         0,1,0,0,1,0,
  2338.         0,1,1,1,0,0,
  2339.         0,1,0,0,1,0,
  2340.         0,1,0,0,1,0,
  2341.         0,1,1,1,0,0,
  2342.         0,1,0,0,0,0,
  2343.         /* num: 226 */
  2344.         0,1,1,1,1,0,
  2345.         0,1,0,0,1,0,
  2346.         0,1,0,0,0,0,
  2347.         0,1,0,0,0,0,
  2348.         0,1,0,0,0,0,
  2349.         0,1,0,0,0,0,
  2350.         0,1,0,0,0,0,
  2351.         0,0,0,0,0,0,
  2352.         /* num: 227 */
  2353.         0,0,0,0,0,0,
  2354.         0,1,1,1,1,1,
  2355.         0,0,1,0,1,0,
  2356.         0,0,1,0,1,0,
  2357.         0,0,1,0,1,0,
  2358.         0,0,1,0,1,0,
  2359.         0,0,1,0,1,0,
  2360.         0,0,0,0,0,0,
  2361.         /* num: 228 */
  2362.         0,0,1,0,1,0,
  2363.         0,0,0,0,0,0,
  2364.         0,0,1,1,1,0,
  2365.         0,0,0,0,0,1,
  2366.         0,0,1,1,1,1,
  2367.         0,1,0,0,0,1,
  2368.         0,0,1,1,1,1,
  2369.         0,0,0,0,0,0,
  2370.         /* num: 229 */
  2371.         0,0,0,0,0,0,
  2372.         0,0,0,0,0,0,
  2373.         0,0,1,1,1,1,
  2374.         0,1,0,0,1,0,
  2375.         0,1,0,0,1,0,
  2376.         0,0,1,1,0,0,
  2377.         0,0,0,0,0,0,
  2378.         0,0,0,0,0,0,
  2379.         /* num: 230 */
  2380.         0,0,0,0,0,0,
  2381.         0,0,0,0,0,0,
  2382.         0,1,0,0,1,0,
  2383.         0,1,0,0,1,0,
  2384.         0,1,0,0,1,0,
  2385.         0,1,1,1,0,0,
  2386.         0,1,0,0,0,0,
  2387.         0,1,0,0,0,0,
  2388.         /* num: 231 */
  2389.         0,0,0,0,0,0,
  2390.         0,0,0,0,0,0,
  2391.         0,0,1,0,1,0,
  2392.         0,1,0,1,0,0,
  2393.         0,0,0,1,0,0,
  2394.         0,0,0,1,0,0,
  2395.         0,0,0,1,0,0,
  2396.         0,0,0,0,0,0,
  2397.         /* num: 232 */
  2398.         0,0,1,1,1,0,
  2399.         0,0,0,1,0,0,
  2400.         0,0,1,1,1,0,
  2401.         0,1,0,0,0,1,
  2402.         0,0,1,1,1,0,
  2403.         0,0,0,1,0,0,
  2404.         0,0,1,1,1,0,
  2405.         0,0,0,0,0,0,
  2406.         /* num: 233 */
  2407.         0,0,1,1,0,0,
  2408.         0,1,0,0,1,0,
  2409.         0,1,0,0,1,0,
  2410.         0,1,1,1,1,0,
  2411.         0,1,0,0,1,0,
  2412.         0,1,0,0,1,0,
  2413.         0,0,1,1,0,0,
  2414.         0,0,0,0,0,0,
  2415.         /* num: 234 */
  2416.         0,0,0,0,0,0,
  2417.         0,0,1,1,1,0,
  2418.         0,1,0,0,0,1,
  2419.         0,1,0,0,0,1,
  2420.         0,0,1,0,1,0,
  2421.         0,0,1,0,1,0,
  2422.         0,1,1,0,1,1,
  2423.         0,0,0,0,0,0,
  2424.         /* num: 235 */
  2425.         0,0,1,1,0,0,
  2426.         0,1,0,0,0,0,
  2427.         0,0,1,0,0,0,
  2428.         0,0,0,1,0,0,
  2429.         0,0,1,1,1,0,
  2430.         0,1,0,0,1,0,
  2431.         0,0,1,1,0,0,
  2432.         0,0,0,0,0,0,
  2433.         /* num: 236 */
  2434.         0,0,0,0,0,0,
  2435.         0,0,0,0,0,0,
  2436.         0,0,1,0,1,0,
  2437.         0,1,0,1,0,1,
  2438.         0,1,0,1,0,1,
  2439.         0,0,1,0,1,0,
  2440.         0,0,0,0,0,0,
  2441.         0,0,0,0,0,0,
  2442.         /* num: 237 */
  2443.         0,0,0,0,0,0,
  2444.         0,0,0,1,0,0,
  2445.         0,0,1,1,1,0,
  2446.         0,1,0,1,0,1,
  2447.         0,1,0,1,0,1,
  2448.         0,0,1,1,1,0,
  2449.         0,0,0,1,0,0,
  2450.         0,0,0,0,0,0,
  2451.         /* num: 238 */
  2452.         0,0,0,0,0,0,
  2453.         0,0,1,1,1,0,
  2454.         0,1,0,0,0,0,
  2455.         0,1,1,1,1,0,
  2456.         0,1,0,0,0,0,
  2457.         0,0,1,1,1,0,
  2458.         0,0,0,0,0,0,
  2459.         0,0,0,0,0,0,
  2460.         /* num: 239 */
  2461.         0,0,0,0,0,0,
  2462.         0,0,1,1,0,0,
  2463.         0,1,0,0,1,0,
  2464.         0,1,0,0,1,0,
  2465.         0,1,0,0,1,0,
  2466.         0,1,0,0,1,0,
  2467.         0,0,0,0,0,0,
  2468.         0,0,0,0,0,0,
  2469.         /* num: 240 */
  2470.         0,0,0,0,0,0,
  2471.         0,1,1,1,1,0,
  2472.         0,0,0,0,0,0,
  2473.         0,1,1,1,1,0,
  2474.         0,0,0,0,0,0,
  2475.         0,1,1,1,1,0,
  2476.         0,0,0,0,0,0,
  2477.         0,0,0,0,0,0,
  2478.         /* num: 241 */
  2479.         0,0,0,0,0,0,
  2480.         0,0,0,1,0,0,
  2481.         0,0,1,1,1,0,
  2482.         0,0,0,1,0,0,
  2483.         0,0,0,0,0,0,
  2484.         0,0,1,1,1,0,
  2485.         0,0,0,0,0,0,
  2486.         0,0,0,0,0,0,
  2487.         /* num: 242 */
  2488.         0,1,0,0,0,0,
  2489.         0,0,1,1,0,0,
  2490.         0,0,0,0,1,0,
  2491.         0,0,1,1,0,0,
  2492.         0,1,0,0,0,0,
  2493.         0,0,0,0,0,0,
  2494.         0,1,1,1,1,0,
  2495.         0,0,0,0,0,0,
  2496.         /* num: 243 */
  2497.         0,0,0,0,0,0,
  2498.         0,0,0,0,0,0,
  2499.         1,1,1,1,1,1,
  2500.         1,1,1,0,0,0,
  2501.         1,0,0,1,1,0,
  2502.         1,0,0,0,0,1,
  2503.         1,0,0,0,0,0,
  2504.         1,1,1,1,1,1,
  2505.         /* num: 244 */
  2506.         0,0,0,0,0,0,
  2507.         0,0,0,0,0,0,
  2508.         1,1,1,1,1,1,
  2509.         0,0,0,1,1,1,
  2510.         0,1,1,0,0,1,
  2511.         1,0,0,0,0,1,
  2512.         0,0,0,0,0,1,
  2513.         1,1,1,1,1,1,
  2514.         /* num: 245 */
  2515.         0,0,0,1,0,0,
  2516.         0,0,0,1,0,0,
  2517.         0,0,0,1,0,0,
  2518.         0,0,0,1,0,0,
  2519.         0,0,0,1,0,0,
  2520.         0,1,0,1,0,0,
  2521.         0,0,1,0,0,0,
  2522.         0,0,0,0,0,0,
  2523.         /* num: 246 */
  2524.         0,0,1,0,1,0,
  2525.         0,0,0,0,0,0,
  2526.         0,0,1,1,1,0,
  2527.         0,1,0,0,0,1,
  2528.         0,1,0,0,0,1,
  2529.         0,1,0,0,0,1,
  2530.         0,0,1,1,1,0,
  2531.         0,0,0,0,0,0,
  2532.         /* num: 247 */
  2533.         1,1,1,1,1,0,
  2534.         1,1,1,1,1,0,
  2535.         1,1,1,1,1,0,
  2536.         1,1,1,1,1,0,
  2537.         1,1,1,1,1,0,
  2538.         1,1,1,1,1,0,
  2539.         1,1,1,1,1,0,
  2540.         1,1,1,1,1,0,
  2541.         /* num: 248 */
  2542.         1,1,1,1,0,0,
  2543.         1,1,1,1,0,0,
  2544.         1,1,1,1,0,0,
  2545.         1,1,1,1,0,0,
  2546.         1,1,1,1,0,0,
  2547.         1,1,1,1,0,0,
  2548.         1,1,1,1,0,0,
  2549.         1,1,1,1,0,0,
  2550.         /* num: 249 */
  2551.         1,1,1,0,0,0,
  2552.         1,1,1,0,0,0,
  2553.         1,1,1,0,0,0,
  2554.         1,1,1,0,0,0,
  2555.         1,1,1,0,0,0,
  2556.         1,1,1,0,0,0,
  2557.         1,1,1,0,0,0,
  2558.         1,1,1,0,0,0,
  2559.         /* num: 250 */
  2560.         1,1,0,0,0,0,
  2561.         1,1,0,0,0,0,
  2562.         1,1,0,0,0,0,
  2563.         1,1,0,0,0,0,
  2564.         1,1,0,0,0,0,
  2565.         1,1,0,0,0,0,
  2566.         1,1,0,0,0,0,
  2567.         1,1,0,0,0,0,
  2568.         /* num: 251 */
  2569.         1,0,0,0,0,0,
  2570.         1,0,0,0,0,0,
  2571.         1,0,0,0,0,0,
  2572.         1,0,0,0,0,0,
  2573.         1,0,0,0,0,0,
  2574.         1,0,0,0,0,0,
  2575.         1,0,0,0,0,0,
  2576.         1,0,0,0,0,0,
  2577.         /* num: 252 */
  2578.         0,0,1,0,1,0,
  2579.         0,0,0,0,0,0,
  2580.         0,1,0,0,1,0,
  2581.         0,1,0,0,1,0,
  2582.         0,1,0,0,1,0,
  2583.         0,1,0,1,1,0,
  2584.         0,0,1,0,1,0,
  2585.         0,0,0,0,0,0,
  2586.         /* num: 253 */
  2587.         0,1,1,0,0,0,
  2588.         0,0,0,1,0,0,
  2589.         0,0,1,0,0,0,
  2590.         0,1,1,1,0,0,
  2591.         0,0,0,0,0,0,
  2592.         0,0,0,0,0,0,
  2593.         0,0,0,0,0,0,
  2594.         0,0,0,0,0,0,
  2595.         /* num: 254 */
  2596.         0,0,0,0,0,0,
  2597.         0,0,0,0,0,0,
  2598.         0,0,0,0,0,0,
  2599.         0,1,1,1,1,0,
  2600.         1,1,0,0,1,0,
  2601.         1,1,0,0,1,1,
  2602.         1,1,1,1,1,0,
  2603.         0,0,1,1,1,1,
  2604.         /* num: 255 */
  2605.         0,1,0,0,1,0,
  2606.         1,1,1,1,1,1,
  2607.         0,1,0,0,1,0,
  2608.         0,1,0,0,1,0,
  2609.         1,1,1,1,1,1,
  2610.         0,1,0,0,1,0,
  2611.         0,0,0,0,0,0,
  2612.         0,0,0,0,0,0
  2613. ];
  2614.  
  2615.  
  2616. } // Font()
  2617. </script>
  2618.  
  2619. <script>
  2620. function Script() {
  2621.  
  2622. this.CreateInterpreter = function() {
  2623.     return new Interpreter();
  2624. };
  2625.  
  2626. this.CreateUtils = function() {
  2627.     return new Utils();
  2628. };
  2629.  
  2630. var Interpreter = function() {
  2631.     var env = new Environment();
  2632.     var parser = new Parser( env );
  2633.  
  2634.     this.SetDialogBuffer = function(buffer) { env.SetDialogBuffer( buffer ); };
  2635.  
  2636.     // TODO -- maybe this should return a string instead othe actual script??
  2637.     this.Compile = function(scriptName, scriptStr) {
  2638.         // console.log("COMPILE");
  2639.         var script = parser.Parse( scriptStr );
  2640.         env.SetScript( scriptName, script );
  2641.     }
  2642.     this.Run = function(scriptName, exitHandler) { // Runs pre-compiled script
  2643.         // console.log("RUN");
  2644.         env.GetScript( scriptName )
  2645.             .Eval( env, function() { if(exitHandler!=null) exitHandler(); } );
  2646.  
  2647.         // console.log("SERIALIZE!!!!");
  2648.         // console.log( env.GetScript( scriptName ).Serialize() );
  2649.     }
  2650.     this.Interpret = function(scriptStr, exitHandler) { // Compiles and runs code immediately
  2651.         // console.log("INTERPRET");
  2652.         var script = parser.Parse( scriptStr );
  2653.         script.Eval( env, function() { if(exitHandler!=null) exitHandler(); } );
  2654.     }
  2655.     this.HasScript = function(name) { return env.HasScript(name); };
  2656.  
  2657.     this.ResetEnvironment = function() {
  2658.         env = new Environment();
  2659.         parser = new Parser( env );
  2660.     }
  2661.  
  2662.     // TODO : move to utils?
  2663.     // for reading in dialog from the larger file format
  2664.     this.ReadDialogScript = function(lines, i) {
  2665.         return parser.ReadDialogScript(lines,i);
  2666.     }
  2667.  
  2668.     this.Parse = function(scriptStr) { // parses a script but doesn't save it
  2669.         return parser.Parse( scriptStr );
  2670.     }
  2671.     this.Eval = function(scripTree, exitHandler) { // runs a script stored externally
  2672.         scripTree.Eval( env, function() { if(exitHandler!=null) exitHandler(); } );
  2673.     }
  2674.  
  2675.     this.CreateExpression = function(expStr) {
  2676.         return parser.CreateExpression( expStr );
  2677.     }
  2678.  
  2679.     this.SetVariable = function(name,value,useHandler) {
  2680.         env.SetVariable(name,value,useHandler);
  2681.     }
  2682.  
  2683.     this.DeleteVariable = function(name,useHandler) {
  2684.         env.DeleteVariable(name,useHandler);
  2685.     }
  2686.     this.HasVariable = function(name) {
  2687.         return env.HasVariable(name);
  2688.     }
  2689.  
  2690.     this.SetOnVariableChangeHandler = function(onVariableChange) {
  2691.         env.SetOnVariableChangeHandler(onVariableChange);
  2692.     }
  2693.     this.GetVariableNames = function() {
  2694.         return env.GetVariableNames();
  2695.     }
  2696.     this.GetVariable = function(name) {
  2697.         return env.GetVariable(name);
  2698.     }
  2699. }
  2700.  
  2701.  
  2702. var Utils = function() {
  2703.     // for editor ui
  2704.     this.CreateDialogBlock = function(children,doIndentFirstLine) {
  2705.         if(doIndentFirstLine === undefined) doIndentFirstLine = true;
  2706.         var block = new BlockNode( BlockMode.Dialog, doIndentFirstLine );
  2707.         for(var i = 0; i < children.length; i++) {
  2708.             block.AddChild( children[i] );
  2709.         }
  2710.         return block;
  2711.     }
  2712.  
  2713.     this.ChangeSequenceType = function(oldSequence,type) {
  2714.         if(type === "sequence") {
  2715.             return new SequenceNode( oldSequence.options );
  2716.         }
  2717.         else if(type === "cycle") {
  2718.             return new CycleNode( oldSequence.options );
  2719.         }
  2720.         else if(type === "shuffle") {
  2721.             return new ShuffleNode( oldSequence.options );
  2722.         }
  2723.         return oldSequence;
  2724.     }
  2725.  
  2726.     this.CreateSequenceBlock = function() {
  2727.         var option1 = new BlockNode( BlockMode.Dialog, false /*doIndentFirstLine*/ );
  2728.         var option2 = new BlockNode( BlockMode.Dialog, false /*doIndentFirstLine*/ );
  2729.         var sequence = new SequenceNode( [ option1, option2 ] );
  2730.         var block = new BlockNode( BlockMode.Code );
  2731.         block.AddChild( sequence );
  2732.         return block;
  2733.     }
  2734.  
  2735.     this.CreateIfBlock = function() {
  2736.         var leftNode = new BlockNode( BlockMode.Code );
  2737.         leftNode.AddChild( new FuncNode("item", [new LiteralNode("0")] ) );
  2738.         var rightNode = new LiteralNode( 1 );
  2739.         var condition1 = new ExpNode("==", leftNode, rightNode );
  2740.  
  2741.         var condition2 = new ElseNode();
  2742.  
  2743.         var result1 = new BlockNode( BlockMode.Dialog );
  2744.         var result2 = new BlockNode( BlockMode.Dialog );
  2745.  
  2746.         var ifNode = new IfNode( [ condition1, condition2 ], [ result1, result2 ] );
  2747.         var block = new BlockNode( BlockMode.Code );
  2748.         block.AddChild( ifNode );
  2749.         return block;
  2750.     }
  2751. }
  2752.  
  2753.  
  2754. /* BUILT-IN FUNCTIONS */ // TODO: better way to encapsulate these?
  2755. function sayFunc(environment,parameters,onReturn) {
  2756.     // console.log("SAY FUNC");
  2757.     // console.log(parameters);
  2758.     if( parameters[0] != undefined && parameters[0] != null ) {
  2759.         // console.log(parameters[0]);
  2760.         // console.log(parameters[0].toString());
  2761.         // var textStr = parameters[0].toString();
  2762.         var textStr = "" + parameters[0];
  2763.         // console.log(textStr);
  2764.         var onFinishHandler = function() {
  2765.             // console.log("FINISHED PRINTING ---- SCRIPT");
  2766.             onReturn(null);
  2767.         }; // called when dialog is finished printing
  2768.         environment.GetDialogBuffer().AddText( textStr, onFinishHandler );
  2769.     }
  2770.     else
  2771.         onReturn(null);
  2772. }
  2773.  
  2774. function linebreakFunc(environment,parameters,onReturn) {
  2775.     // console.log("LINEBREAK FUNC");
  2776.     environment.GetDialogBuffer().AddLinebreak();
  2777.     onReturn(null);
  2778. }
  2779.  
  2780. function itemFunc(environment,parameters,onReturn) {
  2781.     var itemId = parameters[0];
  2782.     if(names.item.has(itemId)) itemId = names.item.get(itemId); // id is actually a name
  2783.     var itemCount = player().inventory[itemId] ? player().inventory[itemId] : 0; // TODO : ultimately the environment should include a reference to the game state
  2784.     // console.log("ITEM FUNC " + itemId + " " + itemCount);
  2785.     onReturn(itemCount);
  2786. }
  2787.  
  2788. function addOrRemoveTextEffect(environment,name) {
  2789.     if( environment.GetDialogBuffer().HasTextEffect(name) )
  2790.         environment.GetDialogBuffer().RemoveTextEffect(name);
  2791.     else
  2792.         environment.GetDialogBuffer().AddTextEffect(name);
  2793. }
  2794.  
  2795. function rainbowFunc(environment,parameters,onReturn) {
  2796.     addOrRemoveTextEffect(environment,"rbw");
  2797.     onReturn(null);
  2798. }
  2799.  
  2800. // TODO : should the colors use a parameter instead of special names?
  2801. function color1Func(environment,parameters,onReturn) {
  2802.     addOrRemoveTextEffect(environment,"clr1");
  2803.     onReturn(null);
  2804. }
  2805.  
  2806. function color2Func(environment,parameters,onReturn) {
  2807.     addOrRemoveTextEffect(environment,"clr2");
  2808.     onReturn(null);
  2809. }
  2810.  
  2811. function color3Func(environment,parameters,onReturn) {
  2812.     addOrRemoveTextEffect(environment,"clr3");
  2813.     onReturn(null);
  2814. }
  2815.  
  2816. function wavyFunc(environment,parameters,onReturn) {
  2817.     addOrRemoveTextEffect(environment,"wvy");
  2818.     onReturn(null);
  2819. }
  2820.  
  2821. function shakyFunc(environment,parameters,onReturn) {
  2822.     addOrRemoveTextEffect(environment,"shk");
  2823.     onReturn(null);
  2824. }
  2825.  
  2826. /* BUILT-IN OPERATORS */
  2827. function setExp(environment,left,right,onReturn) {
  2828.     // console.log("SET " + left.name);
  2829.  
  2830.     if(left.type != "variable") {
  2831.         // not a variable! return null and hope for the best D:
  2832.         onReturn( null );
  2833.         return;
  2834.     }
  2835.  
  2836.     right.Eval(environment,function(rVal) {
  2837.         environment.SetVariable( left.name, rVal );
  2838.         // console.log("VAL " + environment.GetVariable( left.name ) );
  2839.         left.Eval(environment,function(lVal) {
  2840.             onReturn( lVal );
  2841.         });
  2842.     });
  2843. }
  2844. function equalExp(environment,left,right,onReturn) {
  2845.     // console.log("EVAL EQUAL");
  2846.     // console.log(left);
  2847.     // console.log(right);
  2848.     right.Eval(environment,function(rVal){
  2849.         left.Eval(environment,function(lVal){
  2850.             onReturn( lVal === rVal );
  2851.         });
  2852.     });
  2853. }
  2854. function greaterExp(environment,left,right,onReturn) {
  2855.     right.Eval(environment,function(rVal){
  2856.         left.Eval(environment,function(lVal){
  2857.             onReturn( lVal > rVal );
  2858.         });
  2859.     });
  2860. }
  2861. function lessExp(environment,left,right,onReturn) {
  2862.     right.Eval(environment,function(rVal){
  2863.         left.Eval(environment,function(lVal){
  2864.             onReturn( lVal < rVal );
  2865.         });
  2866.     });
  2867. }
  2868. function greaterEqExp(environment,left,right,onReturn) {
  2869.     right.Eval(environment,function(rVal){
  2870.         left.Eval(environment,function(lVal){
  2871.             onReturn( lVal >= rVal );
  2872.         });
  2873.     });
  2874. }
  2875. function lessEqExp(environment,left,right,onReturn) {
  2876.     right.Eval(environment,function(rVal){
  2877.         left.Eval(environment,function(lVal){
  2878.             onReturn( lVal <= rVal );
  2879.         });
  2880.     });
  2881. }
  2882. function multExp(environment,left,right,onReturn) {
  2883.     right.Eval(environment,function(rVal){
  2884.         left.Eval(environment,function(lVal){
  2885.             onReturn( lVal * rVal );
  2886.         });
  2887.     });
  2888. }
  2889. function divExp(environment,left,right,onReturn) {
  2890.     right.Eval(environment,function(rVal){
  2891.         left.Eval(environment,function(lVal){
  2892.             onReturn( lVal / rVal );
  2893.         });
  2894.     });
  2895. }
  2896. function addExp(environment,left,right,onReturn) {
  2897.     right.Eval(environment,function(rVal){
  2898.         left.Eval(environment,function(lVal){
  2899.             onReturn( lVal + rVal );
  2900.         });
  2901.     });
  2902. }
  2903. function subExp(environment,left,right,onReturn) {
  2904.     right.Eval(environment,function(rVal){
  2905.         left.Eval(environment,function(lVal){
  2906.             onReturn( lVal - rVal );
  2907.         });
  2908.     });
  2909. }
  2910.  
  2911. /* ENVIRONMENT */
  2912. var Environment = function() {
  2913.     var dialogBuffer = null;
  2914.     this.SetDialogBuffer = function(buffer) { dialogBuffer = buffer; };
  2915.     this.GetDialogBuffer = function() { return dialogBuffer; };
  2916.  
  2917.     var functionMap = new Map();
  2918.     functionMap.set("say", sayFunc);
  2919.     functionMap.set("br", linebreakFunc);
  2920.     functionMap.set("item", itemFunc);
  2921.     functionMap.set("rbw", rainbowFunc);
  2922.     functionMap.set("clr1", color1Func);
  2923.     functionMap.set("clr2", color2Func);
  2924.     functionMap.set("clr3", color3Func);
  2925.     functionMap.set("wvy", wavyFunc);
  2926.     functionMap.set("shk", shakyFunc);
  2927.  
  2928.     this.HasFunction = function(name) { return functionMap.has(name); };
  2929.     this.EvalFunction = function(name,parameters,onReturn) {
  2930.         // console.log(functionMap);
  2931.         // console.log(name);
  2932.         functionMap.get( name )( this, parameters, onReturn );
  2933.     }
  2934.  
  2935.     var variableMap = new Map();
  2936.  
  2937.     this.HasVariable = function(name) { return variableMap.has(name); };
  2938.     this.GetVariable = function(name) { return variableMap.get(name); };
  2939.     this.SetVariable = function(name,value,useHandler) {
  2940.         // console.log("SET VARIABLE " + name + " = " + value);
  2941.         if(useHandler === undefined) useHandler = true;
  2942.         variableMap.set(name, value);
  2943.         if(onVariableChangeHandler != null && useHandler)
  2944.             onVariableChangeHandler(name);
  2945.     };
  2946.     this.DeleteVariable = function(name,useHandler) {
  2947.         if(useHandler === undefined) useHandler = true;
  2948.         if(variableMap.has(name)) {
  2949.             variableMap.delete(name);
  2950.             if(onVariableChangeHandler != null && useHandler)
  2951.                 onVariableChangeHandler(name);
  2952.         }
  2953.     };
  2954.  
  2955.     var operatorMap = new Map();
  2956.     operatorMap.set("=", setExp);
  2957.     operatorMap.set("==", equalExp);
  2958.     operatorMap.set(">", greaterExp);
  2959.     operatorMap.set("<", lessExp);
  2960.     operatorMap.set(">=", greaterEqExp);
  2961.     operatorMap.set("<=", lessEqExp);
  2962.     operatorMap.set("*", multExp);
  2963.     operatorMap.set("/", divExp);
  2964.     operatorMap.set("+", addExp);
  2965.     operatorMap.set("-", subExp);
  2966.  
  2967.     this.HasOperator = function(sym) { return operatorMap.get(sym); };
  2968.     this.EvalOperator = function(sym,left,right,onReturn) {
  2969.         operatorMap.get( sym )( this, left, right, onReturn );
  2970.     }
  2971.  
  2972.     var scriptMap = new Map();
  2973.     this.HasScript = function(name) { return scriptMap.has(name); };
  2974.     this.GetScript = function(name) { return scriptMap.get(name); };
  2975.     this.SetScript = function(name,script) { scriptMap.set(name, script); };
  2976.  
  2977.     var onVariableChangeHandler = null;
  2978.     this.SetOnVariableChangeHandler = function(onVariableChange) {
  2979.         onVariableChangeHandler = onVariableChange;
  2980.     }
  2981.     this.GetVariableNames = function() {
  2982.         return Array.from( variableMap.keys() );
  2983.     }
  2984. }
  2985.  
  2986. function leadingWhitespace(depth) {
  2987.     var str = "";
  2988.     for(var i = 0; i < depth; i++) {
  2989.         str += "  "; // two spaces per indent
  2990.     }
  2991.     // console.log("WHITESPACE " + depth + " ::" + str + "::");
  2992.     return str;
  2993. }
  2994.  
  2995. /* NODES */
  2996. var TreeRelationship = function() {
  2997.     this.parent = null;
  2998.     this.children = [];
  2999.     this.AddChild = function(node) {
  3000.         this.children.push( node );
  3001.         node.parent = this;
  3002.     };
  3003.  
  3004.     this.VisitAll = function(visitor) {
  3005.         visitor.Visit( this );
  3006.         for( var i = 0; i < this.children.length; i++ ) {
  3007.             this.children[i].VisitAll( visitor );
  3008.         }
  3009.     };
  3010. }
  3011.  
  3012. var BlockMode = {
  3013.     Code : "code",
  3014.     Dialog : "dialog"
  3015. };
  3016.  
  3017. var BlockNode = function(mode, doIndentFirstLine) {
  3018.     Object.assign( this, new TreeRelationship() );
  3019.     // Object.assign( this, new Runnable() );
  3020.     this.type = "block";
  3021.     this.mode = mode;
  3022.  
  3023.     this.Eval = function(environment,onReturn) {
  3024.         // console.log("EVAL BLOCK " + this.children.length);
  3025.  
  3026.         if( this.onEnter != null ) this.onEnter();
  3027.  
  3028.         var lastVal = null;
  3029.         var i = 0;
  3030.         function evalChildren(children,done) {
  3031.             if(i < children.length) {
  3032.                 // console.log(">> CHILD " + i);
  3033.                 children[i].Eval( environment, function(val) {
  3034.                     // console.log("<< CHILD " + i);
  3035.                     lastVal = val;
  3036.                     i++;
  3037.                     evalChildren(children,done);
  3038.                 } );
  3039.             }
  3040.             else {
  3041.                 done();
  3042.             }
  3043.         };
  3044.         var self = this;
  3045.         evalChildren( this.children, function() {
  3046.             if( self.onExit != null ) self.onExit();
  3047.             onReturn(lastVal);
  3048.         } );
  3049.     }
  3050.  
  3051.     if(doIndentFirstLine === undefined) doIndentFirstLine = true; // This is just for serialization
  3052.  
  3053.     this.Serialize = function(depth) {
  3054.         if(depth === undefined) depth = 0;
  3055.  
  3056.         console.log("SERIALIZE BLOCK!!!");
  3057.         console.log(depth);
  3058.         console.log(doIndentFirstLine);
  3059.  
  3060.         var str = "";
  3061.         var lastNode = null;
  3062.         if (this.mode === BlockMode.Code) str += "{"; // todo: increase scope of Sym?
  3063.         for (var i = 0; i < this.children.length; i++) {
  3064.  
  3065.             var curNode = this.children[i];
  3066.  
  3067.             if(curNode.type === "block" && lastNode && lastNode.type === "block" && !isBlockWithNoNewline(curNode) && !isBlockWithNoNewline(lastNode))
  3068.                 str += "\n";
  3069.  
  3070.             var shouldIndentFirstLine = (i == 0 && doIndentFirstLine);
  3071.             var shouldIndentAfterLinebreak = (lastNode && lastNode.type === "function" && lastNode.name === "br");
  3072.             if(this.mode === BlockMode.Dialog && (shouldIndentFirstLine || shouldIndentAfterLinebreak))
  3073.                 str += leadingWhitespace(depth);
  3074.             str += curNode.Serialize(depth);
  3075.             lastNode = curNode;
  3076.         }
  3077.         if (this.mode === BlockMode.Code) str += "}";
  3078.         return str;
  3079.     }
  3080. }
  3081.  
  3082. function isBlockWithNoNewline(node) {
  3083.     return isTextEffectBlock(node) || isMultilineListBlock(node);
  3084. }
  3085.  
  3086. function isTextEffectBlock(node) {
  3087.     if(node.type === "block") {
  3088.         if(node.children.length > 0 && node.children[0].type === "function") {
  3089.             var func = node.children[0];
  3090.             if(func.name === "clr1" || func.name === "clr2" || func.name === "clr3" || func.name === "wvy" || func.name === "shk" || func.name === "rbw") {
  3091.                 return true;
  3092.             }
  3093.         }
  3094.     }
  3095.     return false;
  3096. }
  3097.  
  3098. function isMultilineListBlock(node) {
  3099.     if(node.type === "block") {
  3100.         if(node.children.length > 0) {
  3101.             var child = node.children[0];
  3102.             if(child.type === "sequence" || child.type === "cycle" || child.type === "shuffle" || child.type === "if") {
  3103.                 return true;
  3104.             }
  3105.         }
  3106.     }
  3107.     return false;
  3108. }
  3109.  
  3110. var FuncNode = function(name,arguments) {
  3111.     Object.assign( this, new TreeRelationship() );
  3112.     // Object.assign( this, new Runnable() );
  3113.     this.type = "function";
  3114.     this.name = name;
  3115.     this.arguments = arguments;
  3116.  
  3117.     this.Eval = function(environment,onReturn) {
  3118.  
  3119.         if( this.onEnter != null ) this.onEnter();
  3120.  
  3121.         // console.log("FUNC");
  3122.         // console.log(this.arguments);
  3123.         var argumentValues = [];
  3124.         var i = 0;
  3125.         function evalArgs(arguments,done) {
  3126.             if(i < arguments.length) {
  3127.                 // Evaluate each argument
  3128.                 arguments[i].Eval( environment, function(val) {
  3129.                     argumentValues.push( val );
  3130.                     i++;
  3131.                     evalArgs(arguments,done);
  3132.                 } );
  3133.             }
  3134.             else {
  3135.                 done();
  3136.             }
  3137.         };
  3138.         var self = this; // hack to deal with scope
  3139.         evalArgs( this.arguments, function() {
  3140.             // Then evaluate the function
  3141.             // console.log("ARGS");
  3142.             // console.log(argumentValues);
  3143.  
  3144.             if( self.onExit != null ) self.onExit();
  3145.  
  3146.             environment.EvalFunction( self.name, argumentValues, onReturn );
  3147.         } );
  3148.     }
  3149.  
  3150.     this.Serialize = function(depth) {
  3151.         var isDialogBlock = this.parent.mode && this.parent.mode === BlockMode.Dialog;
  3152.         if(isDialogBlock && this.name === "say") {
  3153.             // TODO this could cause problems with "real" say functions
  3154.             return this.arguments[0].value; // first argument should be the text of the {say} func
  3155.         }
  3156.         else if(isDialogBlock && this.name === "br") {
  3157.             return "\n";
  3158.         }
  3159.         else {
  3160.             var str = "";
  3161.             str += this.name;
  3162.             for(var i = 0; i < this.arguments.length; i++) {
  3163.                 str += " ";
  3164.                 str += this.arguments[i].Serialize(depth);
  3165.             }
  3166.             return str;
  3167.         }
  3168.     }
  3169. }
  3170.  
  3171. var LiteralNode = function(value) {
  3172.     Object.assign( this, new TreeRelationship() );
  3173.     // Object.assign( this, new Runnable() );
  3174.     this.type = "literal";
  3175.     this.value = value;
  3176.  
  3177.     this.Eval = function(environment,onReturn) {
  3178.         onReturn(this.value);
  3179.     }
  3180.  
  3181.     this.Serialize = function(depth) {
  3182.         var str = "";
  3183.  
  3184.         if(this.value === null)
  3185.             return str;
  3186.  
  3187.         if(typeof this.value === "string") str += '"';
  3188.         str += this.value;
  3189.         if(typeof this.value === "string") str += '"';
  3190.  
  3191.         return str;
  3192.     }
  3193. }
  3194.  
  3195. var VarNode = function(name) {
  3196.     Object.assign( this, new TreeRelationship() );
  3197.     // Object.assign( this, new Runnable() );
  3198.     this.type = "variable";
  3199.     this.name = name;
  3200.  
  3201.     this.Eval = function(environment,onReturn) {
  3202.         // console.log("EVAL " + this.name + " " + environment.HasVariable(this.name) + " " + environment.GetVariable(this.name));
  3203.         if( environment.HasVariable(this.name) )
  3204.             onReturn( environment.GetVariable( this.name ) );
  3205.         else
  3206.             onReturn(null); // not a valid variable -- return null and hope that's ok
  3207.     } // TODO: might want to store nodes in the variableMap instead of values???
  3208.  
  3209.     this.Serialize = function(depth) {
  3210.         var str = "" + this.name;
  3211.         return str;
  3212.     }
  3213. }
  3214.  
  3215. var ExpNode = function(operator, left, right) {
  3216.     Object.assign( this, new TreeRelationship() );
  3217.     this.type = "operator";
  3218.     this.operator = operator;
  3219.     this.left = left;
  3220.     this.right = right;
  3221.  
  3222.     this.Eval = function(environment,onReturn) {
  3223.         // console.log("EVAL " + this.operator);
  3224.         var self = this; // hack to deal with scope
  3225.         environment.EvalOperator( this.operator, this.left, this.right,
  3226.             function(val){
  3227.                 // console.log("EVAL EXP " + self.operator + " " + val);
  3228.                 onReturn(val);
  3229.             } );
  3230.         // NOTE : sadly this pushes a lot of complexity down onto the actual operator methods
  3231.     }
  3232.  
  3233.     this.Serialize = function(depth) {
  3234.         var isNegativeNumber = this.operator === "-" && this.left.type === "literal" && this.left.value === null;
  3235.  
  3236.         if(!isNegativeNumber) {
  3237.             var str = "";
  3238.             str += this.left.Serialize(depth);
  3239.             str += " " + this.operator + " ";
  3240.             str += this.right.Serialize(depth);
  3241.             return str;
  3242.         }
  3243.         else {
  3244.             return this.operator + this.right.Serialize(depth); // hacky but seems to work
  3245.         }
  3246.     }
  3247.  
  3248.     this.VisitAll = function(visitor) {
  3249.         visitor.Visit( this );
  3250.         if(this.left != null)
  3251.             this.left.VisitAll( visitor );
  3252.         if(this.right != null)
  3253.             this.right.VisitAll( visitor );
  3254.     };
  3255. }
  3256.  
  3257. var SequenceBase = function() {
  3258.     this.Serialize = function(depth) {
  3259.         var str = "";
  3260.         str += this.type + "\n";
  3261.         for (var i = 0; i < this.options.length; i++) {
  3262.             // console.log("SERIALIZE SEQUENCE ");
  3263.             // console.log(depth);
  3264.             str += leadingWhitespace(depth + 1) + Sym.List + " " + this.options[i].Serialize(depth + 2) + "\n";
  3265.         }
  3266.         str += leadingWhitespace(depth);
  3267.         return str;
  3268.     }
  3269.  
  3270.     this.VisitAll = function(visitor) {
  3271.         visitor.Visit( this );
  3272.         for( var i = 0; i < this.options.length; i++ ) {
  3273.             this.options[i].VisitAll( visitor );
  3274.         }
  3275.     };
  3276. }
  3277.  
  3278. var SequenceNode = function(options) {
  3279.     Object.assign( this, new TreeRelationship() );
  3280.     Object.assign( this, new SequenceBase() );
  3281.     this.type = "sequence";
  3282.     this.options = options;
  3283.  
  3284.     var index = 0;
  3285.     this.Eval = function(environment,onReturn) {
  3286.         // console.log("SEQUENCE " + index);
  3287.         this.options[index].Eval( environment, onReturn );
  3288.  
  3289.         var next = index + 1;
  3290.         if(next < this.options.length)
  3291.             index = next;
  3292.     }
  3293. }
  3294.  
  3295. var CycleNode = function(options) {
  3296.     Object.assign( this, new TreeRelationship() );
  3297.     Object.assign( this, new SequenceBase() );
  3298.     this.type = "cycle";
  3299.     this.options = options;
  3300.  
  3301.     var index = 0;
  3302.     this.Eval = function(environment,onReturn) {
  3303.         // console.log("CYCLE " + index);
  3304.         this.options[index].Eval( environment, onReturn );
  3305.  
  3306.         var next = index + 1;
  3307.         if(next < this.options.length)
  3308.             index = next;
  3309.         else
  3310.             index = 0;
  3311.     }
  3312. }
  3313.  
  3314. var ShuffleNode = function(options) {
  3315.     Object.assign( this, new TreeRelationship() );
  3316.     Object.assign( this, new SequenceBase() );
  3317.     this.type = "shuffle";
  3318.     this.options = options;
  3319.  
  3320.     var optionsShuffled = [];
  3321.     function shuffle(options) {
  3322.         optionsShuffled = [];
  3323.         var optionsUnshuffled = options.slice();
  3324.         while(optionsUnshuffled.length > 0) {
  3325.             var i = Math.floor( Math.random() * optionsUnshuffled.length );
  3326.             optionsShuffled.push( optionsUnshuffled.splice(i,1)[0] );
  3327.         }
  3328.     }
  3329.     shuffle(this.options);
  3330.  
  3331.     var index = 0;
  3332.     this.Eval = function(environment,onReturn) {
  3333.         // OLD RANDOM VERSION
  3334.         // var index = Math.floor(Math.random() * this.options.length);
  3335.         // this.options[index].Eval( environment, onReturn );
  3336.  
  3337.         optionsShuffled[index].Eval( environment, onReturn );
  3338.        
  3339.         index++;
  3340.         if (index >= this.options.length) {
  3341.             shuffle(this.options);
  3342.             index = 0;
  3343.         }
  3344.     }
  3345. }
  3346.  
  3347. var IfNode = function(conditions, results, isSingleLine) {
  3348.     Object.assign( this, new TreeRelationship() );
  3349.     this.type = "if";
  3350.     this.conditions = conditions;
  3351.     this.results = results;
  3352.  
  3353.     this.Eval = function(environment,onReturn) {
  3354.         // console.log("EVAL IF");
  3355.         var i = 0;
  3356.         var self = this;
  3357.         function TestCondition() {
  3358.             // console.log("EVAL " + i);
  3359.             self.conditions[i].Eval(environment, function(val) {
  3360.                 // console.log(val);
  3361.                 if(val == true) {
  3362.                     self.results[i].Eval(environment, onReturn);
  3363.                 }
  3364.                 else if(i+1 < self.conditions.length) {
  3365.                     i++;
  3366.                     TestCondition(); // test next condition
  3367.                 }
  3368.                 else {
  3369.                     onReturn(null); // out of conditions and none were true
  3370.                 }
  3371.             });
  3372.         };
  3373.         TestCondition();
  3374.     }
  3375.  
  3376.     if(isSingleLine === undefined) isSingleLine = false; // This is just for serialization
  3377.  
  3378.     this.Serialize = function(depth) {
  3379.         var str = "";
  3380.         if(isSingleLine) {
  3381.             str += this.conditions[0].Serialize() + " ? " + this.results[0].Serialize();
  3382.             if(this.conditions.length > 1 && this.conditions[1].type === "else")
  3383.                 str += " : " + this.results[1].Serialize();
  3384.         }
  3385.         else {
  3386.             str += "\n";
  3387.             for (var i = 0; i < this.conditions.length; i++) {
  3388.                 str += leadingWhitespace(depth + 1) + Sym.List + " " + this.conditions[i].Serialize(depth) + " ?\n";
  3389.                 str += this.results[i].Serialize(depth + 2) + "\n";
  3390.             }
  3391.             str += leadingWhitespace(depth);
  3392.         }
  3393.         return str;
  3394.     }
  3395.  
  3396.     this.IsSingleLine = function() {
  3397.         return isSingleLine;
  3398.     }
  3399.  
  3400.     this.VisitAll = function(visitor) {
  3401.         visitor.Visit( this );
  3402.         for( var i = 0; i < this.conditions.length; i++ ) {
  3403.             this.conditions[i].VisitAll( visitor );
  3404.         }
  3405.         for( var i = 0; i < this.results.length; i++ ) {
  3406.             this.results[i].VisitAll( visitor );
  3407.         }
  3408.     };
  3409. }
  3410.  
  3411. var ElseNode = function() {
  3412.     Object.assign( this, new TreeRelationship() );
  3413.     this.type = "else";
  3414.  
  3415.     this.Eval = function(environment,onReturn) {
  3416.         onReturn(true);
  3417.     }
  3418.  
  3419.     this.Serialize = function() {
  3420.         return "else";
  3421.     }
  3422. }
  3423.  
  3424. var Sym = {
  3425.     // DialogOpen : "/\"",
  3426.     // DialogClose : "\"/",
  3427.     DialogOpen : '"""',
  3428.     DialogClose : '"""',
  3429.     CodeOpen : "{",
  3430.     CodeClose : "}",
  3431.     Linebreak : "\n", // just call it "break" ?
  3432.     Separator : ":",
  3433.     List : "-",
  3434.     String : '"'
  3435. };
  3436.  
  3437. var Parser = function(env) {
  3438.     var environment = env;
  3439.  
  3440.     this.Parse = function(scriptStr) {
  3441.         // console.log("NEW PARSE!!!!!!");
  3442.  
  3443.         // TODO : make this work for single-line, no dialog block scripts
  3444.  
  3445.         var state = new ParserState( new BlockNode(BlockMode.Dialog), scriptStr );
  3446.  
  3447.         if( state.MatchAhead(Sym.DialogOpen) ) {
  3448.             // multi-line dialog block
  3449.             var dialogStr = state.ConsumeBlock( Sym.DialogOpen, Sym.DialogClose );
  3450.             state = new ParserState( new BlockNode(BlockMode.Dialog), dialogStr );
  3451.             state = ParseDialog( state );
  3452.         }
  3453.         // else if( state.MatchAhead(Sym.CodeOpen) ) { // NOTE: This causes problems when you lead with a code block
  3454.         //  // code-block: should this ever happen?
  3455.         //  state = ParseCodeBlock( state );
  3456.         // }
  3457.         else {
  3458.             // single-line dialog block
  3459.             state = ParseDialog( state );
  3460.         }
  3461.  
  3462.         // console.log( state.rootNode );
  3463.         return state.rootNode;
  3464.     };
  3465.  
  3466.     this.ReadDialogScript = function(lines, i) {
  3467.         var scriptStr = "";
  3468.         if (lines[i] === Sym.DialogOpen) {
  3469.             scriptStr += lines[i] + "\n";
  3470.             i++;
  3471.             while(lines[i] != Sym.DialogClose) {
  3472.                 scriptStr += lines[i] + "\n";
  3473.                 i++;
  3474.             }
  3475.             scriptStr += lines[i];
  3476.             i++;
  3477.         }
  3478.         else {
  3479.             scriptStr += lines[i];
  3480.         }
  3481.         return { script:scriptStr, index:i };
  3482.     }
  3483.  
  3484.     var ParserState = function( rootNode, str ) {
  3485.         this.rootNode = rootNode;
  3486.         this.curNode = this.rootNode;
  3487.  
  3488.         var sourceStr = str;
  3489.         var i = 0;
  3490.         this.Index = function() { return i; };
  3491.         this.Count = function() { return sourceStr.length; };
  3492.         this.Done = function() { return i >= sourceStr.length; };
  3493.         this.Char = function() { return sourceStr[i]; };
  3494.         this.Step = function(n) { if(n===undefined) n=1; i += n; };
  3495.         this.MatchAhead = function(str) {
  3496.             // console.log(str);
  3497.             str = "" + str; // hack to turn single chars into strings
  3498.             // console.log(str);
  3499.             // console.log(str.length);
  3500.             for(var j = 0; j < str.length; j++) {
  3501.                 if( i + j >= sourceStr.length )
  3502.                     return false;
  3503.                 else if( str[j] != sourceStr[i+j] )
  3504.                     return false;
  3505.             }
  3506.             return true;
  3507.         }
  3508.         this.Peak = function(end) {
  3509.             var str = "";
  3510.             var j = i;
  3511.             // console.log(j);
  3512.             while(j < sourceStr.length && end.indexOf( sourceStr[j] ) == -1 ) {
  3513.                 str += sourceStr[j];
  3514.                 j++;
  3515.             }
  3516.             // console.log("PEAK ::" + str + "::");
  3517.             return str;
  3518.         }
  3519.         this.ConsumeBlock = function( open, close ) {
  3520.             var startIndex = i;
  3521.  
  3522.             var matchCount = 0;
  3523.             if( this.MatchAhead( open ) ) {
  3524.                 matchCount++;
  3525.                 this.Step( open.length );
  3526.             }
  3527.  
  3528.             while( matchCount > 0 && !this.Done() ) {
  3529.                 if( this.MatchAhead( close ) ) {
  3530.                     matchCount--;
  3531.                     this.Step( close.length );
  3532.                 }
  3533.                 else if( this.MatchAhead( open ) ) {
  3534.                     matchCount++;
  3535.                     this.Step( open.length );
  3536.                 }
  3537.                 else {
  3538.                     this.Step();
  3539.                 }
  3540.             }
  3541.  
  3542.             // console.log("!!! " + startIndex + " " + i);
  3543.  
  3544.             return sourceStr.slice( startIndex + open.length, i - close.length );
  3545.         }
  3546.         this.Print = function() {console.log(sourceStr);};
  3547.     };
  3548.  
  3549.     function ParseDialog(state) {
  3550.         // console.log("PARSE DIALOG");
  3551.         state.Print();
  3552.  
  3553.         // for linebreak logic: add linebreaks after lines with dialog or empty lines (if it's not the very first line)
  3554.         var hasBlock = false;
  3555.         var hasDialog = false;
  3556.         var isFirstLine = true;
  3557.  
  3558.         // console.log("---- PARSE DIALOG ----");
  3559.  
  3560.         var text = "";
  3561.         var addTextNode = function() {
  3562.             // console.log("TEXT " + text.length);
  3563.             if (text.length > 0) {
  3564.                 // console.log("TEXT " + text);
  3565.                 // console.log("text!!");
  3566.                 // console.log([text]);
  3567.  
  3568.                 state.curNode.AddChild( new FuncNode( "say", [new LiteralNode(text)] ) );
  3569.                 text = "";
  3570.  
  3571.                 hasDialog = true;
  3572.             }
  3573.         }
  3574.  
  3575.         while ( !state.Done() ) {
  3576.  
  3577.             if( state.MatchAhead(Sym.CodeOpen) ) {
  3578.                 addTextNode();
  3579.                 state = ParseCodeBlock( state );
  3580.  
  3581.                 // console.log("CODE");
  3582.  
  3583.                 var len = state.curNode.children.length;
  3584.                 if(len > 0 && state.curNode.children[len-1].type === "block") {
  3585.                     var block = state.curNode.children[len-1];
  3586.                     if(isMultilineListBlock(block))
  3587.                         hasDialog = true; // hack to get correct newline behavior for multiline blocks
  3588.                 }
  3589.  
  3590.                 hasBlock = true;
  3591.             }
  3592.             // NOTE: nested dialog blocks disabled for now
  3593.             // else if( state.MatchAhead(Sym.DialogOpen) ) {
  3594.             //  addTextNode();
  3595.             //  state = ParseDialogBlock( state ); // These can be nested (should they though???)
  3596.  
  3597.             //  hasBlock = true;
  3598.             // }
  3599.             else {
  3600.                 if ( state.MatchAhead(Sym.Linebreak) ) {
  3601.                     addTextNode();
  3602.  
  3603.                     /*
  3604.                     NOTES:
  3605.                     linebreaks SHOULD happen on
  3606.                     - lines with text (including the first or last line)
  3607.                     - empty lines (that are NOT the first or last line)
  3608.                     linebreaks should NOT happen on
  3609.                     - lines with only CODE blocks
  3610.                     - empty FIRST or LAST lines
  3611.  
  3612.                     also, apparently:
  3613.                     - NEVER line break on the last line
  3614.                     */
  3615.                     var isLastLine = (state.Index() + 1) == state.Count();
  3616.                     // console.log("block " + hasBlock);
  3617.                     // console.log("dialog " + hasDialog);
  3618.                     var isEmptyLine = !hasBlock && !hasDialog;
  3619.                     // console.log("empty " + isEmptyLine);
  3620.                     var isValidEmptyLine = isEmptyLine && !(isFirstLine || isLastLine);
  3621.                     // console.log("valid empty " + isValidEmptyLine);
  3622.                     var shouldAddLinebreak = (hasDialog || isValidEmptyLine) && !isLastLine; // last clause is a hack (but it works - why?)
  3623.                     // console.log("LINEBREAK? " + shouldAddLinebreak);
  3624.                     if( shouldAddLinebreak ) {
  3625.                         // console.log("NEWLINE");
  3626.                         // console.log("empty? " + isEmptyLine);
  3627.                         // console.log("dialog? " + hasDialog);
  3628.                         state.curNode.AddChild( new FuncNode( "br", [] ) ); // use function or character?
  3629.                     }
  3630.  
  3631.                     // linebreak logic
  3632.                     isFirstLine = false;
  3633.                     hasBlock = false;
  3634.                     hasDialog = false;
  3635.  
  3636.                     text = "";
  3637.                 }
  3638.                 else {
  3639.                     text += state.Char();
  3640.                 }
  3641.                 state.Step();
  3642.             }
  3643.  
  3644.         }
  3645.         addTextNode();
  3646.  
  3647.         // console.log("---- PARSE DIALOG ----");
  3648.  
  3649.         // console.log(state);
  3650.         return state;
  3651.     }
  3652.  
  3653.     function ParseDialogBlock(state) {
  3654.         var dialogStr = state.ConsumeBlock( Sym.DialogOpen, Sym.DialogClose );
  3655.  
  3656.         var dialogState = new ParserState( new BlockNode(BlockMode.Dialog), dialogStr );
  3657.         dialogState = ParseDialog( dialogState );
  3658.  
  3659.         state.curNode.AddChild( dialogState.rootNode );
  3660.  
  3661.         return state;
  3662.     }
  3663.  
  3664.     function ParseIf(state) {
  3665.         var conditionStrings = [];
  3666.         var resultStrings = [];
  3667.         var curIndex = -1;
  3668.         var isNewline = true;
  3669.         var isConditionDone = false;
  3670.         var codeBlockCount = 0;
  3671.  
  3672.         while( !state.Done() ) {
  3673.             if(state.Char() === Sym.CodeOpen)
  3674.                 codeBlockCount++;
  3675.             else if(state.Char() === Sym.CodeClose)
  3676.                 codeBlockCount--;
  3677.  
  3678.             var isWhitespace = (state.Char() === " " || state.Char() === "\t");
  3679.             var isSkippableWhitespace = isNewline && isWhitespace;
  3680.             var isNewListItem = isNewline && (codeBlockCount <= 0) && (state.Char() === Sym.List);
  3681.  
  3682.             if(isNewListItem) {
  3683.                 curIndex++;
  3684.                 isConditionDone = false;
  3685.                 conditionStrings[curIndex] = "";
  3686.                 resultStrings[curIndex] = "";
  3687.             }
  3688.             else if(curIndex > -1) {
  3689.                 if(!isConditionDone) {
  3690.                     if(state.Char() === "?" || state.Char() === "\n") { // TODO: use Sym
  3691.                         // end of condition
  3692.                         isConditionDone = true;
  3693.                     }
  3694.                     else {
  3695.                         // read in condition
  3696.                         conditionStrings[curIndex] += state.Char();
  3697.                     }
  3698.                 }
  3699.                 else {
  3700.                     // read in result
  3701.                     if(!isSkippableWhitespace)
  3702.                         resultStrings[curIndex] += state.Char();
  3703.                 }
  3704.             }
  3705.  
  3706.             isNewline = (state.Char() === Sym.Linebreak) || isSkippableWhitespace || isNewListItem;
  3707.  
  3708.             state.Step();
  3709.         }
  3710.  
  3711.         // console.log("PARSE IF:");
  3712.         // console.log(conditionStrings);
  3713.         // console.log(resultStrings);
  3714.  
  3715.         var conditions = [];
  3716.         for(var i = 0; i < conditionStrings.length; i++) {
  3717.             var str = conditionStrings[i].trim();
  3718.             if(str === "else") {
  3719.                 conditions.push( new ElseNode() );
  3720.             }
  3721.             else {
  3722.                 var exp = CreateExpression( str );
  3723.                 conditions.push( exp );
  3724.             }
  3725.         }
  3726.  
  3727.         var results = [];
  3728.         for(var i = 0; i < resultStrings.length; i++) {
  3729.             var str = resultStrings[i];
  3730.             var dialogBlockState = new ParserState( new BlockNode(BlockMode.Dialog), str );
  3731.             dialogBlockState = ParseDialog( dialogBlockState );
  3732.             var dialogBlock = dialogBlockState.rootNode;
  3733.             results.push( dialogBlock );
  3734.         }
  3735.  
  3736.         state.curNode.AddChild( new IfNode( conditions, results ) );
  3737.  
  3738.         return state;
  3739.     }
  3740.  
  3741.     function IsSequence(str) {
  3742.         // console.log("IsSequence? " + str);
  3743.         return str === "sequence" || str === "cycle" || str === "shuffle";
  3744.     }
  3745.  
  3746.     // TODO: don't forget about eating whitespace
  3747.     function ParseSequence(state, sequenceType) {
  3748.         // console.log("SEQUENCE " + sequenceType);
  3749.         state.Print();
  3750.  
  3751.         var isNewline = false;
  3752.         var itemStrings = [];
  3753.         var curItemIndex = -1; // -1 indicates not reading an item yet
  3754.         var codeBlockCount = 0;
  3755.  
  3756.         while( !state.Done() ) {
  3757.             if(state.Char() === Sym.CodeOpen)
  3758.                 codeBlockCount++;
  3759.             else if(state.Char() === Sym.CodeClose)
  3760.                 codeBlockCount--;
  3761.  
  3762.             var isWhitespace = (state.Char() === " " || state.Char() === "\t");
  3763.             var isSkippableWhitespace = isNewline && isWhitespace;
  3764.             var isNewListItem = isNewline && (codeBlockCount <= 0) && (state.Char() === Sym.List);
  3765.  
  3766.             if(isNewListItem) {
  3767.                 // console.log("found next list item");
  3768.                 curItemIndex++;
  3769.                 itemStrings[curItemIndex] = "";
  3770.             }
  3771.             else if(curItemIndex > -1) {
  3772.                 if(!isSkippableWhitespace)
  3773.                     itemStrings[curItemIndex] += state.Char();
  3774.             }
  3775.  
  3776.             isNewline = (state.Char() === Sym.Linebreak) || isSkippableWhitespace || isNewListItem;
  3777.  
  3778.             // console.log(state.Char());
  3779.             state.Step();
  3780.         }
  3781.         // console.log(itemStrings);
  3782.         // console.log("SEQUENCE DONE");
  3783.  
  3784.         var options = [];
  3785.         for(var i = 0; i < itemStrings.length; i++) {
  3786.             var str = itemStrings[i];
  3787.             var dialogBlockState = new ParserState( new BlockNode( BlockMode.Dialog, false /* doIndentFirstLine */ ), str );
  3788.             dialogBlockState = ParseDialog( dialogBlockState );
  3789.             var dialogBlock = dialogBlockState.rootNode;
  3790.             options.push( dialogBlock );
  3791.         }
  3792.  
  3793.         // console.log(options);
  3794.  
  3795.         if(sequenceType === "sequence")
  3796.             state.curNode.AddChild( new SequenceNode( options ) );
  3797.         else if(sequenceType === "cycle")
  3798.             state.curNode.AddChild( new CycleNode( options ) );
  3799.         else if(sequenceType === "shuffle")
  3800.             state.curNode.AddChild( new ShuffleNode( options ) );
  3801.  
  3802.         return state;
  3803.     }
  3804.  
  3805.     function ParseFunction(state, funcName) {
  3806.         var args = [];
  3807.  
  3808.         var curSymbol = "";
  3809.         function OnSymbolEnd() {
  3810.             curSymbol = curSymbol.trim();
  3811.             console.log("PARAMTER " + curSymbol);
  3812.             args.push( StringToValue(curSymbol) );
  3813.             console.log(args);
  3814.             curSymbol = "";
  3815.         }
  3816.  
  3817.         while( !( state.Char() === "\n" || state.Done() ) ) {
  3818.             if( state.MatchAhead(Sym.CodeOpen) ) {
  3819.                 var codeBlockState = new ParserState( new BlockNode(BlockMode.Code), state.ConsumeBlock( Sym.CodeOpen, Sym.CodeClose ) );
  3820.                 codeBlockState = ParseCode( codeBlockState );
  3821.                 var codeBlock = codeBlockState.rootNode;
  3822.                 args.push( codeBlock );
  3823.                 curSymbol = "";
  3824.             }
  3825.             else if( state.MatchAhead(Sym.String) ) {
  3826.                 /* STRING LITERAL */
  3827.                 var str = state.ConsumeBlock(Sym.String, Sym.String);
  3828.                 // console.log("STRING " + str);
  3829.                 args.push( new LiteralNode(str) );
  3830.                 curSymbol = "";
  3831.             }
  3832.             else if(state.Char() === " " && curSymbol.length > 0) {
  3833.                 OnSymbolEnd();
  3834.             }
  3835.             else {
  3836.                 curSymbol += state.Char();
  3837.             }
  3838.             state.Step();
  3839.         }
  3840.  
  3841.         if(curSymbol.length > 0) {
  3842.             OnSymbolEnd();
  3843.         }
  3844.  
  3845.         state.curNode.AddChild( new FuncNode( funcName, args ) );
  3846.  
  3847.         return state;
  3848.     }
  3849.  
  3850.     function IsValidVariableName(str) {
  3851.         var reg = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
  3852.         var isValid = reg.test(str);
  3853.         console.log("VALID variable??? " + isValid);
  3854.         return isValid;
  3855.     }
  3856.  
  3857.     function StringToValue(valStr) {
  3858.         if(valStr[0] === Sym.CodeOpen) {
  3859.             // CODE BLOCK!!!
  3860.             var codeStr = (new ParserState( null, valStr )).ConsumeBlock(Sym.CodeOpen, Sym.CodeClose); //hacky
  3861.             var codeBlockState = new ParserState( new BlockNode( BlockMode.Code ), codeStr );
  3862.             codeBlockState = ParseCode( codeBlockState );
  3863.             return codeBlockState.rootNode;
  3864.         }
  3865.         else if(valStr[0] === Sym.String) {
  3866.             // STRING!!
  3867.             console.log("STRING");
  3868.             var str = "";
  3869.             var i = 1;
  3870.             while (i < valStr.length && valStr[i] != Sym.String) {
  3871.                 str += valStr[i];
  3872.                 i++;
  3873.             }
  3874.             console.log(str);
  3875.             return new LiteralNode( str );
  3876.         }
  3877.         else if(valStr === "true") {
  3878.             // BOOL
  3879.             return new LiteralNode( true );
  3880.         }
  3881.         else if(valStr === "false") {
  3882.             // BOOL
  3883.             return new LiteralNode( false );
  3884.         }
  3885.         else if( !isNaN(parseFloat(valStr)) ) {
  3886.             // NUMBER!!
  3887.             // console.log("NUMBER!!! " + valStr);
  3888.             return new LiteralNode( parseFloat(valStr) );
  3889.         }
  3890.         else if(IsValidVariableName(valStr)) {
  3891.             // VARIABLE!!
  3892.             // console.log("VARIABLE");
  3893.             return new VarNode(valStr); // TODO : check for valid potential variables
  3894.         }
  3895.         else {
  3896.             // uh oh
  3897.             return new LiteralNode(null);
  3898.         }
  3899.     }
  3900.  
  3901.     var setSymbol = "=";
  3902.     var ifSymbol = "?";
  3903.     var elseSymbol = ":";
  3904.     // var operatorSymbols = ["==", ">", "<", ">=", "<=", "*", "/", "+", "-"];
  3905.     var operatorSymbols = ["-", "+", "/", "*", "<=", ">=", "<", ">", "=="]; // operators need to be in reverse order
  3906.     function CreateExpression(expStr) {
  3907.         expStr = expStr.trim();
  3908.  
  3909.         function IsInsideString(index) {
  3910.             var inString = false;
  3911.             for(var i = 0; i < expStr.length; i++) {
  3912.                 if(expStr[i] === Sym.String)
  3913.                     inString = !inString;
  3914.  
  3915.                 if(index === i)
  3916.                     return inString;
  3917.             }
  3918.             return false;
  3919.         }
  3920.  
  3921.         function IsInsideCode(index) {
  3922.             var count = 0;
  3923.             for(var i = 0; i < expStr.length; i++) {
  3924.                 if(expStr[i] === Sym.CodeOpen)
  3925.                     count++;
  3926.                 else if(expStr[i] === Sym.CodeClose)
  3927.                     count--;
  3928.  
  3929.                 if(index === i)
  3930.                     return count > 0;
  3931.             }
  3932.             return false;
  3933.         }
  3934.    
  3935.         var operator = null;
  3936.  
  3937.         // set is special because other operator can look like it, and it has to go first in the order of operations
  3938.         var setIndex = expStr.indexOf(setSymbol);
  3939.         if( setIndex > -1 && !IsInsideString(setIndex) && !IsInsideCode(setIndex) ) { // it might be a set operator
  3940.             if( expStr[setIndex+1] != "=" && expStr[setIndex-1] != ">" && expStr[setIndex-1] != "<" ) {
  3941.                 // ok it actually IS a set operator and not ==, >=, or <=
  3942.                 operator = setSymbol;
  3943.                 var variableName = expStr.substring(0,setIndex).trim(); // TODO : valid variable name testing
  3944.                 var left = IsValidVariableName(variableName) ? new VarNode( variableName ) : new LiteralNode(null);
  3945.                 var right = CreateExpression( expStr.substring(setIndex+setSymbol.length) );
  3946.                 var exp = new ExpNode( operator, left, right );
  3947.                 return exp;
  3948.             }
  3949.         }
  3950.  
  3951.         // special if "expression" for single-line if statements
  3952.         var ifIndex = expStr.indexOf(ifSymbol);
  3953.         if( ifIndex > -1 && !IsInsideString(ifIndex) && !IsInsideCode(ifIndex) ) {
  3954.             operator = ifSymbol;
  3955.             var conditionStr = expStr.substring(0,ifIndex).trim();
  3956.             var conditions = [ CreateExpression(conditionStr) ];
  3957.  
  3958.             var resultStr = expStr.substring(ifIndex+ifSymbol.length);
  3959.             var results = [];
  3960.             function AddResult(str) {
  3961.                 var dialogBlockState = new ParserState( new BlockNode(BlockMode.Dialog), str );
  3962.                 dialogBlockState = ParseDialog( dialogBlockState );
  3963.                 var dialogBlock = dialogBlockState.rootNode;
  3964.                 results.push( dialogBlock );
  3965.             }
  3966.  
  3967.             var elseIndex = resultStr.indexOf(elseSymbol); // does this need to test for strings?
  3968.             if(elseIndex > -1) {
  3969.                 conditions.push( new ElseNode() );
  3970.  
  3971.                 var elseStr = resultStr.substring(elseIndex+elseSymbol.length);
  3972.                 var resultStr = resultStr.substring(0,elseIndex);
  3973.  
  3974.                 AddResult( resultStr.trim() );
  3975.                 AddResult( elseStr.trim() );
  3976.             }
  3977.             else {
  3978.                 AddResult( resultStr.trim() );
  3979.             }
  3980.  
  3981.             return new IfNode( conditions, results, true /*isSingleLine*/ );
  3982.         }
  3983.  
  3984.         for( var i = 0; (operator == null) && (i < operatorSymbols.length); i++ ) {
  3985.             var opSym = operatorSymbols[i];
  3986.             var opIndex = expStr.indexOf( opSym );
  3987.             if( opIndex > -1 && !IsInsideString(opIndex) && !IsInsideCode(opIndex) ) {
  3988.                 operator = opSym;
  3989.                 var left = CreateExpression( expStr.substring(0,opIndex) );
  3990.                 var right = CreateExpression( expStr.substring(opIndex+opSym.length) );
  3991.                 var exp = new ExpNode( operator, left, right );
  3992.                 return exp;
  3993.             }
  3994.         }
  3995.  
  3996.         if( operator == null ) {
  3997.             return StringToValue(expStr);
  3998.         }
  3999.     }
  4000.     this.CreateExpression = CreateExpression;
  4001.  
  4002.     function ParseExpression(state) {
  4003.         var line = state.Peak( [Sym.Linebreak] );
  4004.         // console.log("EXPRESSION " + line);
  4005.         var exp = CreateExpression( line );
  4006.         // console.log(exp);
  4007.         state.curNode.AddChild( exp );
  4008.         state.Step( line.length );
  4009.         return state;
  4010.     }
  4011.  
  4012.     function ParseCode(state) {
  4013.         // TODO : how do I do this parsing??? one expression per block? or per line?
  4014.         while ( !state.Done() ) {
  4015.  
  4016.             if( state.Char() === " " || state.Char() === "\t" || state.Char() === "\n" ) { // TODO: symbols? IsWhitespace func?
  4017.                 state.Step(); // consume whitespace
  4018.             }
  4019.             else if( state.MatchAhead(Sym.CodeOpen) ) {
  4020.                 state = ParseCodeBlock( state );
  4021.             }
  4022.             // NOTE: nested dialog blocks disabled for now
  4023.             // else if( state.MatchAhead(Sym.DialogOpen) ) {
  4024.             //  state = ParseDialogBlock( state ); // These can be nested (should they though???)
  4025.             // }
  4026.             else if( state.Char() === Sym.List && (state.Peak([]).indexOf("?") > -1) ) { // TODO : symbols? matchahead?
  4027.                 // console.log("PEAK IF " + state.Peak( ["?"] ));
  4028.                 state = ParseIf( state );
  4029.             }
  4030.             else if( environment.HasFunction( state.Peak( [" "] ) ) ) { // TODO --- what about newlines???
  4031.                 var funcName = state.Peak( [" "] );
  4032.                 state.Step( funcName.length );
  4033.                 state = ParseFunction( state, funcName );
  4034.             }
  4035.             else if( IsSequence( state.Peak( [" ", Sym.Linebreak] ) ) ) {
  4036.                 var sequenceType = state.Peak( [" ", Sym.Linebreak] );
  4037.                 state.Step( sequenceType.length );
  4038.                 state = ParseSequence( state, sequenceType );
  4039.             }
  4040.             else {
  4041.                 state = ParseExpression( state );
  4042.             }
  4043.         }
  4044.  
  4045.         return state;
  4046.     }
  4047.  
  4048.     function ParseCodeBlock(state) {
  4049.         var codeStr = state.ConsumeBlock( Sym.CodeOpen, Sym.CodeClose );
  4050.  
  4051.         // console.log("PARSE CODE");
  4052.         // console.log(codeStr);
  4053.  
  4054.         var codeState = new ParserState( new BlockNode(BlockMode.Code), codeStr );
  4055.         codeState = ParseCode( codeState );
  4056.        
  4057.         state.curNode.AddChild( codeState.rootNode );
  4058.  
  4059.         return state;
  4060.     }
  4061.  
  4062. }
  4063.  
  4064. } // Script()
  4065. </script>
  4066.  
  4067. <script>
  4068. function Dialog() {
  4069.  
  4070. this.CreateRenderer = function() {
  4071.     return new DialogRenderer();
  4072. };
  4073.  
  4074. this.CreateBuffer = function() {
  4075.     return new DialogBuffer();
  4076. };
  4077.  
  4078. var DialogRenderer = function() {
  4079.     var textboxInfo = {
  4080.         img : null,
  4081.         width : 104,
  4082.         height : 8+4+2+5, //8 for text, 4 for top-bottom padding, 2 for line padding, 5 for arrow
  4083.         top : 12,
  4084.         left : 12,
  4085.         bottom : 12, //for drawing it from the bottom
  4086.     };
  4087.    
  4088.     var font = new Font();
  4089.  
  4090.     var context = null;
  4091.     this.AttachContext = function(c) {
  4092.         context = c;
  4093.     };
  4094.  
  4095.     this.ClearTextbox = function() {
  4096.         if(context == null) return;
  4097.         textboxInfo.img = context.createImageData(textboxInfo.width*scale, textboxInfo.height*scale);
  4098.     };
  4099.  
  4100.     var isCentered = false;
  4101.     this.SetCentered = function(centered) {
  4102.         isCentered = centered;
  4103.     };
  4104.  
  4105.     this.DrawTextbox = function() {
  4106.         if(context == null) return;
  4107.         if (isCentered) {
  4108.             context.putImageData(textboxInfo.img, textboxInfo.left*scale, ((height/2)-(textboxInfo.height/2))*scale);
  4109.         }
  4110.         else if (player().y < mapsize/2) {
  4111.             //bottom
  4112.             context.putImageData(textboxInfo.img, textboxInfo.left*scale, (height-textboxInfo.bottom-textboxInfo.height)*scale);
  4113.         }
  4114.         else {
  4115.             //top
  4116.             context.putImageData(textboxInfo.img, textboxInfo.left*scale, textboxInfo.top*scale);
  4117.         }
  4118.     };
  4119.  
  4120.     var arrowdata = [
  4121.         1,1,1,1,1,
  4122.         0,1,1,1,0,
  4123.         0,0,1,0,0
  4124.     ];
  4125.     this.DrawNextArrow = function() {
  4126.         // console.log("draw arrow!");
  4127.         var top = (textboxInfo.height-5) * scale;
  4128.         var left = (textboxInfo.width-(5+4)) * scale;
  4129.         for (var y = 0; y < 3; y++) {
  4130.             for (var x = 0; x < 5; x++) {
  4131.                 var i = (y * 5) + x;
  4132.                 if (arrowdata[i] == 1) {
  4133.                     //scaling nonsense
  4134.                     for (var sy = 0; sy < scale; sy++) {
  4135.                         for (var sx = 0; sx < scale; sx++) {
  4136.                             var pxl = 4 * ( ((top+(y*scale)+sy) * (textboxInfo.width*scale)) + (left+(x*scale)+sx) );
  4137.                             textboxInfo.img.data[pxl+0] = 255;
  4138.                             textboxInfo.img.data[pxl+1] = 255;
  4139.                             textboxInfo.img.data[pxl+2] = 255;
  4140.                             textboxInfo.img.data[pxl+3] = 255;
  4141.                         }
  4142.                     }
  4143.                 }
  4144.             }
  4145.         }
  4146.     };
  4147.  
  4148.     var text_scale = 2; //using a different scaling factor for text feels like cheating... but it looks better
  4149.     this.DrawChar = function(char, row, col) {
  4150.         char.offset = {x:0, y:0};
  4151.         char.SetPosition(row,col);
  4152.         char.ApplyEffects(effectTime);
  4153.         var charData = font.getChar( char.char );
  4154.         var top = (4 * scale) + (row * 2 * scale) + (row * 8 * text_scale) + Math.floor( char.offset.y );
  4155.         var left = (4 * scale) + (col * 6 * text_scale) + Math.floor( char.offset.x );
  4156.         for (var y = 0; y < 8; y++) {
  4157.             for (var x = 0; x < 6; x++) {
  4158.                 var i = (y * 6) + x;
  4159.                 if ( charData[i] == 1 ) {
  4160.  
  4161.                     //scaling nonsense
  4162.                     for (var sy = 0; sy < text_scale; sy++) {
  4163.                         for (var sx = 0; sx < text_scale; sx++) {
  4164.                             var pxl = 4 * ( ((top+(y*text_scale)+sy) * (textboxInfo.width*scale)) + (left+(x*text_scale)+sx) );
  4165.                             textboxInfo.img.data[pxl+0] = char.color.r;
  4166.                             textboxInfo.img.data[pxl+1] = char.color.g;
  4167.                             textboxInfo.img.data[pxl+2] = char.color.b;
  4168.                             textboxInfo.img.data[pxl+3] = char.color.a;
  4169.                         }
  4170.                     }
  4171.  
  4172.                    
  4173.                 }
  4174.             }
  4175.         }
  4176.        
  4177.         // call printHandler for character
  4178.         char.OnPrint();
  4179.     };
  4180.  
  4181.     var effectTime = 0; // TODO this variable should live somewhere better
  4182.     this.Draw = function(buffer,dt) { // TODO move out of the buffer?? (into say a dialog box renderer)
  4183.         effectTime += dt;
  4184.  
  4185.         this.ClearTextbox();
  4186.  
  4187.         buffer.ForEachActiveChar( this.DrawChar );
  4188.  
  4189.         if( buffer.CanContinue() )
  4190.             this.DrawNextArrow();
  4191.  
  4192.         this.DrawTextbox();
  4193.  
  4194.         if( buffer.DidPageFinishThisFrame() && onPageFinish != null )
  4195.             onPageFinish();
  4196.     };
  4197.  
  4198.     /* this is a hook for GIF rendering */
  4199.     var onPageFinish = null;
  4200.     this.SetPageFinishHandler = function(handler) {
  4201.         onPageFinish = handler;
  4202.     };
  4203.  
  4204.     this.Reset = function() {
  4205.         effectTime = 0;
  4206.         // TODO - anything else?
  4207.     }
  4208. }
  4209.  
  4210.  
  4211. var DialogBuffer = function() {
  4212.     var buffer = [[[]]]; // holds dialog in an array buffer
  4213.     var pageIndex = 0;
  4214.     var rowIndex = 0;
  4215.     var charIndex = 0;
  4216.     var nextCharTimer = 0;
  4217.     var nextCharMaxTime = 50; // in milliseconds
  4218.     var isDialogReadyToContinue = false;
  4219.     var activeTextEffects = [];
  4220.    
  4221.     this.CurPage = function() { return buffer[ pageIndex ]; };
  4222.     this.CurRow = function() { return this.CurPage()[ rowIndex ]; };
  4223.     this.CurChar = function() { return this.CurRow()[ charIndex ]; };
  4224.     this.CurPageCount = function() { return buffer.length; };
  4225.     this.CurRowCount = function() { return this.CurPage().length; };
  4226.     this.CurCharCount = function() { return this.CurRow().length; };
  4227.  
  4228.     this.ForEachActiveChar = function(handler) { // Iterates over visible characters on the active page
  4229.         var rowCount = rowIndex + 1;
  4230.         for (var i = 0; i < rowCount; i++) {
  4231.             var row = this.CurPage()[i];
  4232.             var charCount = (i == rowIndex) ? charIndex+1 : row.length;
  4233.             // console.log(charCount);
  4234.             for(var j = 0; j < charCount; j++) {
  4235.                 var char = row[j];
  4236.                 if(char)
  4237.                     handler( char, i /*rowIndex*/, j /*colIndex*/ );
  4238.             }
  4239.         }
  4240.     }
  4241.  
  4242.     this.Reset = function() {
  4243.         buffer = [[[]]];
  4244.         pageIndex = 0;
  4245.         rowIndex = 0;
  4246.         charIndex = 0;
  4247.         isDialogReadyToContinue = false;
  4248.  
  4249.         activeTextEffects = [];
  4250.  
  4251.         isActive = false;
  4252.     };
  4253.  
  4254.     this.DoNextChar = function() {
  4255.         // console.log("DO NEXT CHAR");
  4256.  
  4257.         nextCharTimer = 0; //reset timer
  4258.  
  4259.         //time to update characters
  4260.         if (charIndex + 1 < this.CurCharCount()) {
  4261.             //add char to current row
  4262.             charIndex++;
  4263.         }
  4264.         else if (rowIndex + 1 < this.CurRowCount()) {
  4265.             //start next row
  4266.             rowIndex++;
  4267.             charIndex = 0;
  4268.         }
  4269.         else {
  4270.             //the page is full!
  4271.             isDialogReadyToContinue = true;
  4272.             didPageFinishThisFrame = true;
  4273.  
  4274.             // console.log("WAITING FOR INPUT");
  4275.         }
  4276.  
  4277.         // console.log(this.CurChar());
  4278.         if(this.CurChar() != null)
  4279.             this.CurChar().OnPrint(); // make sure we hit the callback before we run out of text
  4280.     };
  4281.  
  4282.     this.Update = function(dt) {
  4283.         didPageFinishThisFrame = false;
  4284.         didFlipPageThisFrame = false;
  4285.         // this.Draw(dt); // TODO move into a renderer object
  4286.         if (isDialogReadyToContinue) {
  4287.             return; //waiting for dialog to be advanced by player
  4288.         }
  4289.  
  4290.         nextCharTimer += dt; //tick timer
  4291.  
  4292.         if (nextCharTimer > nextCharMaxTime) {
  4293.             this.DoNextChar();
  4294.         }
  4295.     };
  4296.  
  4297.     this.Skip = function() {
  4298.         console.log("SKIPPP");
  4299.         didPageFinishThisFrame = false;
  4300.         didFlipPageThisFrame = false;
  4301.         // add new characters until you get to the end of the current line of dialog
  4302.         while (rowIndex < this.CurRowCount()) {
  4303.             this.DoNextChar();
  4304.  
  4305.             if(isDialogReadyToContinue) {
  4306.                 //make sure to push the rowIndex past the end to break out of the loop
  4307.                 rowIndex++;
  4308.                 charIndex = 0;
  4309.             }
  4310.         }
  4311.         rowIndex = this.CurRowCount()-1;
  4312.         charIndex = this.CurCharCount()-1;
  4313.     };
  4314.  
  4315.     this.FlipPage = function() {
  4316.         didFlipPageThisFrame = true;
  4317.         isDialogReadyToContinue = false;
  4318.         pageIndex++;
  4319.         rowIndex = 0;
  4320.         charIndex = 0;
  4321.     }
  4322.  
  4323.     this.EndDialog = function() {
  4324.         console.log("END!!!!");
  4325.         isActive = false; // no more text to show... this should be a sign to stop rendering dialog
  4326.     }
  4327.  
  4328.     this.Continue = function() {
  4329.         console.log("CONTINUE");
  4330.         if (pageIndex + 1 < this.CurPageCount()) {
  4331.             //start next page
  4332.             this.FlipPage();
  4333.             return true; /* hasMoreDialog */
  4334.         }
  4335.         else {
  4336.             //end dialog mode
  4337.             this.EndDialog();
  4338.             return false; /* hasMoreDialog */
  4339.         }
  4340.     };
  4341.  
  4342.     var isActive = false;
  4343.     this.IsActive = function() { return isActive; };
  4344.  
  4345.     this.CanContinue = function() { return isDialogReadyToContinue; };
  4346.  
  4347.     function DialogChar(char,effectList) {
  4348.         this.char = char;
  4349.         this.effectList = effectList.slice(); // clone effect list (since it can change between chars)
  4350.  
  4351.         this.color = { r:255, g:255, b:255, a:255 };
  4352.         this.offset = { x:0, y:0 }; // in pixels (screen pixels?)
  4353.         this.row = 0;
  4354.         this.col = 0;
  4355.         this.SetPosition = function(row,col) {
  4356.             this.row = row;
  4357.             this.col = col;
  4358.         };
  4359.  
  4360.         this.ApplyEffects = function(time) {
  4361.             for(var i = 0; i < this.effectList.length; i++) {
  4362.                 var effectName = this.effectList[i];
  4363.                 TextEffects[ effectName ].DoEffect( this, time );
  4364.             }
  4365.         }
  4366.  
  4367.         var printHandler = null; // optional function to be called once on printing character
  4368.         this.SetPrintHandler = function(handler) {
  4369.             printHandler = handler;
  4370.         }
  4371.         this.OnPrint = function() {
  4372.             if (printHandler != null) {
  4373.                 console.log("PRINT HANDLER ---- DIALOG BUFFER");
  4374.                 printHandler();
  4375.                 printHandler = null; // only call handler once (hacky)
  4376.             }
  4377.         }
  4378.     };
  4379.  
  4380.     function AddWordToCharArray(charArray,word,effectList) {
  4381.         for(var i = 0; i < word.length; i++) {
  4382.             charArray.push( new DialogChar( word[i], effectList ) );
  4383.         }
  4384.         return charArray;
  4385.     }
  4386.  
  4387.     var charsPerRow = 32;
  4388.     this.AddText = function(textStr,onFinishHandler) {
  4389.         console.log("ADD TEXT " + textStr);
  4390.  
  4391.         //process dialog so it's easier to display
  4392.         var words = textStr.split(" ");
  4393.  
  4394.         // var curPageIndex = this.CurPageCount() - 1;
  4395.         // var curRowIndex = this.CurRowCount() - 1;
  4396.         // var curRowArr = this.CurRow();
  4397.  
  4398.         var curPageIndex = buffer.length - 1;
  4399.         var curRowIndex = buffer[curPageIndex].length - 1;
  4400.         var curRowArr = buffer[curPageIndex][curRowIndex];
  4401.  
  4402.         for (var i = 0; i < words.length; i++) {
  4403.             var word = words[i];
  4404.             var wordLength = word.length + ((i == 0) ? 0 : 1);
  4405.             if (curRowArr.length + wordLength <= charsPerRow || curRowArr.length <= 0) {
  4406.                 //stay on same row
  4407.                 var wordWithPrecedingSpace = ((i == 0) ? "" : " ") + word;
  4408.                 curRowArr = AddWordToCharArray( curRowArr, wordWithPrecedingSpace, activeTextEffects );
  4409.             }
  4410.             else if (curRowIndex == 0) {
  4411.                 //start next row
  4412.                 buffer[ curPageIndex ][ curRowIndex ] = curRowArr;
  4413.                 buffer[ curPageIndex ].push( [] );
  4414.                 curRowIndex++;
  4415.                 curRowArr = buffer[ curPageIndex ][ curRowIndex ];
  4416.                 curRowArr = AddWordToCharArray( curRowArr, word, activeTextEffects );
  4417.             }
  4418.             else {
  4419.                 //start next page
  4420.                 buffer[ curPageIndex ][ curRowIndex ] = curRowArr;
  4421.                 buffer.push( [] );
  4422.                 curPageIndex++;
  4423.                 buffer[ curPageIndex ].push( [] );
  4424.                 curRowIndex = 0;
  4425.                 curRowArr = buffer[ curPageIndex ][ curRowIndex ];
  4426.                 curRowArr = AddWordToCharArray( curRowArr, word, activeTextEffects );
  4427.             }
  4428.         }
  4429.  
  4430.         //destroy any empty stuff
  4431.         var lastPage = buffer[ buffer.length-1 ];
  4432.         var lastRow = lastPage[ lastPage.length-1 ];
  4433.         if( lastRow.length == 0 )
  4434.             lastPage.splice( lastPage.length-1, 1 );
  4435.         if( lastPage.length == 0 )
  4436.             buffer.splice( buffer.length-1, 1 );
  4437.  
  4438.         //finish up
  4439.         lastPage = buffer[ buffer.length-1 ];
  4440.         lastRow = lastPage[ lastPage.length-1 ];
  4441.         if( lastRow.length > 0 ) {
  4442.             var lastChar = lastRow[ lastRow.length-1 ];
  4443.             lastChar.SetPrintHandler( onFinishHandler );
  4444.         }
  4445.  
  4446.         console.log(buffer);
  4447.  
  4448.         isActive = true;
  4449.     };
  4450.  
  4451.     this.AddLinebreak = function() {
  4452.         var lastPage = buffer[ buffer.length-1 ];
  4453.         if( lastPage.length <= 1 ) {
  4454.             console.log("LINEBREAK - NEW ROW ");
  4455.             // add new row
  4456.             lastPage.push( [] );
  4457.         }
  4458.         else {
  4459.             // add new page
  4460.             buffer.push( [[]] );
  4461.         }
  4462.         console.log(buffer);
  4463.  
  4464.         isActive = true;
  4465.     }
  4466.  
  4467.     /* new text effects */
  4468.     this.HasTextEffect = function(name) {
  4469.         return activeTextEffects.indexOf( name ) > -1;
  4470.     }
  4471.     this.AddTextEffect = function(name) {
  4472.         activeTextEffects.push( name );
  4473.     }
  4474.     this.RemoveTextEffect = function(name) {
  4475.         activeTextEffects.splice( activeTextEffects.indexOf( name ), 1 );
  4476.     }
  4477.  
  4478.     /* this is a hook for GIF rendering */
  4479.     var didPageFinishThisFrame = false;
  4480.     this.DidPageFinishThisFrame = function(){ return didPageFinishThisFrame; };
  4481.  
  4482.     var didFlipPageThisFrame = false;
  4483.     this.DidFlipPageThisFrame = function(){ return didFlipPageThisFrame; };
  4484. };
  4485.  
  4486. /* NEW TEXT EFFECTS */
  4487. var TextEffects = new Map();
  4488.  
  4489. var RainbowEffect = function() { // TODO - should it be an object or just a method?
  4490.     this.DoEffect = function(char,time) {
  4491.         var h = Math.abs( Math.sin( (time / 600) - (char.col / 8) ) );
  4492.         var rgb = hslToRgb( h, 1, 0.5 );
  4493.         char.color.r = rgb[0];
  4494.         char.color.g = rgb[1];
  4495.         char.color.b = rgb[2];
  4496.         char.color.a = 255;
  4497.     }
  4498. };
  4499. TextEffects["rbw"] = new RainbowEffect();
  4500.  
  4501. var ColorEffect = function(index) {
  4502.     this.DoEffect = function(char) {
  4503.         var pal = getPal( curPal() );
  4504.         var color = pal[ parseInt( index ) ];
  4505.         console.log(color);
  4506.         char.color.r = color[0];
  4507.         char.color.g = color[1];
  4508.         char.color.b = color[2];
  4509.         char.color.a = 255;
  4510.     }
  4511. };
  4512. TextEffects["clr1"] = new ColorEffect(0);
  4513. TextEffects["clr2"] = new ColorEffect(1); // TODO : should I use parameters instead of special names?
  4514. TextEffects["clr3"] = new ColorEffect(2);
  4515.  
  4516. var WavyEffect = function() {
  4517.     this.DoEffect = function(char,time) {
  4518.         char.offset.y += Math.sin( (time / 250) - (char.col / 2) ) * 4;
  4519.     }
  4520. };
  4521. TextEffects["wvy"] = new WavyEffect();
  4522.  
  4523. var ShakyEffect = function() {
  4524.     function disturb(func,time,offset,mult1,mult2) {
  4525.         return func( (time * mult1) - (offset * mult2) );
  4526.     }
  4527.  
  4528.     this.DoEffect = function(char,time) {
  4529.         char.offset.y += 3
  4530.                         * disturb(Math.sin,time,char.col,0.1,0.5)
  4531.                         * disturb(Math.cos,time,char.col,0.3,0.2)
  4532.                         * disturb(Math.sin,time,char.row,2.0,1.0);
  4533.         char.offset.x += 3
  4534.                         * disturb(Math.cos,time,char.row,0.1,1.0)
  4535.                         * disturb(Math.sin,time,char.col,3.0,0.7)
  4536.                         * disturb(Math.cos,time,char.col,0.2,0.3);
  4537.     }
  4538. };
  4539. TextEffects["shk"] = new ShakyEffect();
  4540.  
  4541. } // Dialog()
  4542. </script>
  4543.  
  4544. <script>
  4545. var xhr;
  4546. var canvas;
  4547. var context;
  4548. var ctx;
  4549.  
  4550. var title = "";
  4551. var room = {};
  4552. var tile = {};
  4553. var sprite = {};
  4554. var item = {};
  4555. var dialog = {};
  4556. var palette = {
  4557.     "0" : [[0,0,0],[255,0,0],[255,255,255]] //start off with a default palette (can be overriden)
  4558. };
  4559. var ending = {};
  4560. var variable = {}; // these are starting variable values -- they don't update (or I don't think they will)
  4561. var playerId = "A";
  4562.  
  4563. var names = {
  4564.     room : new Map(),
  4565.     tile : new Map(), // Note: Not currently enabled in the UI
  4566.     sprite : new Map(),
  4567.     item : new Map(),
  4568.     /*dialog : new Map()*/ // TODO
  4569.     /*ending : new Map()*/ // TODO
  4570. };
  4571. function updateNamesFromCurData() {
  4572.     names.room = new Map();
  4573.     for(id in room) {
  4574.         if(room[id].name != undefined && room[id].name != null)
  4575.             names.room.set( room[id].name, id );
  4576.     }
  4577.     names.tile = new Map();
  4578.     for(id in tile) {
  4579.         if(tile[id].name != undefined && tile[id].name != null)
  4580.             names.tile.set( tile[id].name, id );
  4581.     }
  4582.     names.sprite = new Map();
  4583.     for(id in sprite) {
  4584.         if(sprite[id].name != undefined && sprite[id].name != null)
  4585.             names.sprite.set( sprite[id].name, id );
  4586.     }
  4587.     names.item = new Map();
  4588.     for(id in item) {
  4589.         if(item[id].name != undefined && item[id].name != null)
  4590.             names.item.set( item[id].name, id );
  4591.     }
  4592. }
  4593.  
  4594. //stores all image data for tiles, sprites, drawings
  4595. var imageStore = {
  4596.     source: {},
  4597.     render: {}
  4598. };
  4599.  
  4600. var spriteStartLocations = {};
  4601.  
  4602. /* VERSION */
  4603. var version = {
  4604.     major: 4, // for file format / engine changes
  4605.     minor: 6 // for editor changes and bugfixes
  4606. };
  4607. function getEngineVersion() {
  4608.     return version.major + "." + version.minor;
  4609. }
  4610.  
  4611. /* FLAGS */
  4612. var flags;
  4613. function resetFlags() {
  4614.     flags = {
  4615.         ROOM_FORMAT : 0 // 0 = non-comma separated, 1 = comma separated
  4616.     };
  4617. }
  4618. resetFlags(); //init flags on load script
  4619.  
  4620. function clearGameData() {
  4621.     title = "";
  4622.     room = {};
  4623.     tile = {};
  4624.     sprite = {};
  4625.     item = {};
  4626.     dialog = {};
  4627.     palette = { //start off with a default palette (can be overriden)
  4628.         "0" : {
  4629.             name : null,
  4630.             colors : [[0,0,0],[255,0,0],[255,255,255]]
  4631.         }
  4632.     };
  4633.     ending = {};
  4634.     isEnding = false; //todo - correct place for this?
  4635.     variable = {};
  4636.  
  4637.     //stores all image data for tiles, sprites, drawings
  4638.     imageStore = {
  4639.         source: {},
  4640.         render: {}
  4641.     };
  4642.  
  4643.     spriteStartLocations = {};
  4644.  
  4645.     names = {
  4646.         room : new Map(),
  4647.         tile : new Map(),
  4648.         sprite : new Map(),
  4649.         item : new Map()
  4650.     };
  4651. }
  4652.  
  4653. var width = 128;
  4654. var height = 128;
  4655. var scale = 4; //this is stupid but necessary
  4656. var tilesize = 8;
  4657. var mapsize = 16;
  4658.  
  4659. var curRoom = "0";
  4660.  
  4661. var key = {
  4662.     left : 37,
  4663.     right : 39,
  4664.     up : 38,
  4665.     down : 40,
  4666.     space : 32,
  4667.     enter : 13,
  4668.     w : 87,
  4669.     a : 65,
  4670.     s : 83,
  4671.     d : 68,
  4672.     r : 82
  4673. };
  4674.  
  4675. var prevTime = 0;
  4676. var deltaTime = 0;
  4677.  
  4678. //methods used to trigger gif recording
  4679. var didPlayerMoveThisFrame = false;
  4680. var onPlayerMoved = null;
  4681. // var didDialogUpdateThisFrame = false;
  4682. var onDialogUpdate = null;
  4683.  
  4684. //inventory update UI handles
  4685. var onInventoryChanged = null;
  4686. var onVariableChanged = null;
  4687.  
  4688. var isPlayerEmbeddedInEditor = false;
  4689.  
  4690. function getGameNameFromURL() {
  4691.     var game = window.location.hash.substring(1);
  4692.     // console.log("game name --- " + game);
  4693.     return game;
  4694. }
  4695.  
  4696. function attachCanvas(c) {
  4697.     canvas = c;
  4698.     canvas.width = width * scale;
  4699.     canvas.height = width * scale;
  4700.     ctx = canvas.getContext("2d");
  4701.     dialogRenderer.AttachContext(ctx);
  4702. }
  4703.  
  4704. var curGameData = null;
  4705. function load_game(game_data, startWithTitle) {
  4706.     curGameData = game_data; //remember the current game (used to reset the game)
  4707.     dialogBuffer.Reset();
  4708.     scriptInterpreter.ResetEnvironment(); // ensures variables are reset -- is this the best way?
  4709.     // console.log(dialog);
  4710.     parseWorld(game_data);
  4711.     // console.log(dialog);
  4712.     setInitialVariables();
  4713.     renderImages();
  4714.     onready(startWithTitle);
  4715.     // console.log(dialog);
  4716. }
  4717.  
  4718. function reset_cur_game() {
  4719.     if (curGameData == null) return; //can't reset if we don't have the game data
  4720.     stopGame();
  4721.     clearGameData();
  4722.     load_game(curGameData);
  4723. }
  4724.  
  4725. var update_interval = null;
  4726. function onready(startWithTitle) {
  4727.     if(startWithTitle === undefined || startWithTitle === null) startWithTitle = true;
  4728.  
  4729.     clearInterval(loading_interval);
  4730.  
  4731.     document.addEventListener('keydown', onkeydown);
  4732.     document.addEventListener('keyup', onkeyup);
  4733.  
  4734.     canvas.addEventListener('touchstart', ontouchstart);
  4735.     canvas.addEventListener('touchmove', ontouchmove);
  4736.     canvas.addEventListener('touchend', ontouchend);
  4737.  
  4738.     update_interval = setInterval(update,-1);
  4739.  
  4740.     console.log("TITLE ??? " + startWithTitle);
  4741.     if(startWithTitle) // used by editor
  4742.         startNarrating(title);
  4743. }
  4744.  
  4745. function setInitialVariables() {
  4746.     for(id in variable) {
  4747.         var value = variable[id]; // default to string
  4748.         if(value === "true") {
  4749.             value = true;
  4750.         }
  4751.         else if(value === "false") {
  4752.             value = false;
  4753.         }
  4754.         else if(!isNaN(parseFloat(value))) {
  4755.             value = parseFloat(value);
  4756.         }
  4757.         scriptInterpreter.SetVariable(id,value);
  4758.     }
  4759.     scriptInterpreter.SetOnVariableChangeHandler( onVariableChanged );
  4760. }
  4761.  
  4762. // OLD VERSION: DEPRECATED
  4763. // function onTouch(e) {
  4764. //  console.log("MOUSEDOWN");
  4765.  
  4766. //  //dialog mode
  4767. //  // if (isDialogMode) {
  4768. //  if(dialogBuffer.IsActive()) {
  4769.  
  4770. //      if (dialogBuffer.CanContinue()) {
  4771. //          var hasMoreDialog = dialogBuffer.Continue();
  4772. //          if(!hasMoreDialog) {
  4773. //              onExitDialog();
  4774. //          }
  4775. //      }
  4776. //      else {
  4777. //          dialogBuffer.Skip();
  4778. //      }
  4779.  
  4780. //      return;
  4781. //  }
  4782.  
  4783. //  if (isEnding) {
  4784. //      reset_cur_game();
  4785. //      return;
  4786. //  }
  4787.  
  4788. //  //walking mode
  4789. //  var off = getOffset(e);
  4790. //  var x = Math.floor(off.x / (tilesize*scale));
  4791. //  var y = Math.floor(off.y / (tilesize*scale));
  4792.    
  4793. //  //abort if you touch the square you're already on
  4794. //  if (player().x == x && player().y == y) {
  4795. //      return;
  4796. //  }
  4797.  
  4798. //  //did we touch a sprite?
  4799. //  var touchedSprite = null;
  4800. //  for (id in sprite) {
  4801. //      var spr = sprite[id];
  4802. //      if (spr.room === curRoom) {
  4803. //          if (spr.x == x && spr.y == y) {
  4804. //              touchedSprite = id;
  4805. //          }
  4806. //      }
  4807. //  }
  4808.  
  4809. //  //respond to sprite touch
  4810. //  if (touchedSprite) {
  4811. //      var spr = sprite[touchedSprite];
  4812. //      // console.log(Math.abs(player().x - spr.x));
  4813. //      // console.log(Math.abs(player().y - spr.y));
  4814. //      if ( Math.abs(player().x - spr.x) == 0
  4815. //              && Math.abs(player().y - spr.y) == 1 )
  4816. //      {
  4817. //          //touched a sprite next to you
  4818. //      }
  4819. //      else if ( Math.abs(player().y - spr.y) == 0
  4820. //              && Math.abs(player().x - spr.x) == 1 )
  4821. //      {
  4822. //          //touched a sprite next to you
  4823. //      }
  4824. //      else
  4825. //      {
  4826. //          return; //oh no! touched a sprite that's out of range
  4827. //      }
  4828.  
  4829. //      startSpriteDialog( touchedSprite /*spriteId*/ );
  4830.  
  4831. //      return;
  4832. //  }
  4833.  
  4834. //  //did we touch an open square?
  4835. //  var row = room[curRoom].tilemap[y];
  4836. //  // console.log(row);
  4837. //  var til = row[x];
  4838. //  // console.log(til);
  4839. //  if ( room[curRoom].walls.indexOf(til) != -1 ) {
  4840. //      //touched a wall
  4841. //      return;
  4842. //  }
  4843.  
  4844. //  //find path to open square, if there is one
  4845. //  var map = collisionMap(curRoom);
  4846. //  var path = breadthFirstSearch( map, {x:player().x, y:player().y}, {x:x,y:y} );
  4847. //  path = path.slice(1); //remove player's start square
  4848.  
  4849. //  //console.log( pathToString(path) );
  4850.  
  4851. //  player().walkingPath = path;
  4852. // }
  4853.  
  4854. // TODO: this is likely broken
  4855. function breadthFirstSearch(map, from, to) {
  4856.     from.trail = [];
  4857.     var visited = [];
  4858.     var queue = [from];
  4859.     visited.push( posToString(from) );
  4860.  
  4861.     //console.log( "~ bfs ~");
  4862.     //console.log( posToString(from) + " to " + posToString(to) );
  4863.  
  4864.     while ( queue.length > 0 ) {
  4865.  
  4866.         //grab pos from queue and mark as visited
  4867.         var curPos = queue.shift();
  4868.  
  4869.         //console.log( posToString(curPos) );
  4870.         //console.log( ".. " + pathToString(curPos.trail) );
  4871.         //console.log( visited );
  4872.  
  4873.         if (curPos.x == to.x && curPos.y == to.y) {
  4874.             //found a path!
  4875.             var path = curPos.trail.splice(0);
  4876.             path.push( curPos );
  4877.             return path;
  4878.         }
  4879.  
  4880.         //look at neighbors
  4881.         neighbors(curPos).forEach( function(n) {
  4882.             var inBounds = (n.x >= 0 && n.x < 16 && n.y >= 0 && n.y < 16);
  4883.             if (inBounds) {
  4884.                 var noCollision = map[n.y][n.x] <= 0;
  4885.                 var notVisited = visited.indexOf( posToString(n) ) == -1;
  4886.                 if (noCollision && notVisited) {
  4887.                     n.trail = curPos.trail.slice();
  4888.                     n.trail.push(curPos);
  4889.                     queue.push( n );
  4890.                     visited.push( posToString(n) );
  4891.                 }
  4892.             }
  4893.         });
  4894.  
  4895.     }
  4896.  
  4897.     return []; // no path found
  4898. }
  4899.  
  4900. function posToString(pos) {
  4901.     return pos.x + "," + pos.y;
  4902. }
  4903.  
  4904. function pathToString(path) {
  4905.     var s = "";
  4906.     for (i in path) {
  4907.         s += posToString(path[i]) + " ";
  4908.     }
  4909.     return s;
  4910. }
  4911.  
  4912. function neighbors(pos) {
  4913.     var neighborList = [];
  4914.     neighborList.push( {x:pos.x+1, y:pos.y+0} );
  4915.     neighborList.push( {x:pos.x-1, y:pos.y+0} );
  4916.     neighborList.push( {x:pos.x+0, y:pos.y+1} );
  4917.     neighborList.push( {x:pos.x+0, y:pos.y-1} );
  4918.     return neighborList;
  4919. }
  4920.  
  4921. function collisionMap(roomId) {
  4922.     var map = [
  4923.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4924.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4925.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4926.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4927.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4928.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4929.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4930.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4931.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4932.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4933.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4934.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4935.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4936.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4937.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  4938.         [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  4939.     ];
  4940.  
  4941.     for (r in room[roomId].tilemap) {
  4942.         var row = room[roomId].tilemap[r];
  4943.         for (var c = 0; c < row.length; c++) {
  4944.             if (room[roomId].walls.indexOf( row[x] ) != -1) {
  4945.                 map[r][c] = 1;
  4946.             }
  4947.         }
  4948.     }
  4949.  
  4950.     for (id in sprite) {
  4951.         var spr = sprite[id];
  4952.         if (spr.room === roomId) {
  4953.             map[spr.y][spr.x] = 2;
  4954.         }
  4955.     }
  4956.  
  4957.     return map;
  4958. }
  4959.  
  4960. function getOffset(evt) {
  4961.     var offset = { x:0, y:0 };
  4962.  
  4963.     var el = evt.target;
  4964.     var rect = el.getBoundingClientRect();
  4965.  
  4966.     offset.x += rect.left + el.scrollLeft;
  4967.     offset.y += rect.top + el.scrollTop;
  4968.  
  4969.     offset.x = evt.clientX - offset.x;
  4970.     offset.y = evt.clientY - offset.y;
  4971.  
  4972.     return offset;
  4973. }
  4974.  
  4975. function stopGame() {
  4976.     console.log("stop GAME!");
  4977.  
  4978.     document.removeEventListener('keydown', onkeydown);
  4979.     clearInterval(update_interval);
  4980. }
  4981.  
  4982. /* loading animation */
  4983. var loading_anim_data = [
  4984.     [
  4985.         0,1,1,1,1,1,1,0,
  4986.         0,0,1,1,1,1,0,0,
  4987.         0,0,1,1,1,1,0,0,
  4988.         0,0,0,1,1,0,0,0,
  4989.         0,0,0,1,1,0,0,0,
  4990.         0,0,1,0,0,1,0,0,
  4991.         0,0,1,0,0,1,0,0,
  4992.         0,1,1,1,1,1,1,0,
  4993.     ],
  4994.     [
  4995.         0,1,1,1,1,1,1,0,
  4996.         0,0,1,0,0,1,0,0,
  4997.         0,0,1,1,1,1,0,0,
  4998.         0,0,0,1,1,0,0,0,
  4999.         0,0,0,1,1,0,0,0,
  5000.         0,0,1,0,0,1,0,0,
  5001.         0,0,1,1,1,1,0,0,
  5002.         0,1,1,1,1,1,1,0,
  5003.     ],
  5004.     [
  5005.         0,1,1,1,1,1,1,0,
  5006.         0,0,1,0,0,1,0,0,
  5007.         0,0,1,0,0,1,0,0,
  5008.         0,0,0,1,1,0,0,0,
  5009.         0,0,0,1,1,0,0,0,
  5010.         0,0,1,1,1,1,0,0,
  5011.         0,0,1,1,1,1,0,0,
  5012.         0,1,1,1,1,1,1,0,
  5013.     ],
  5014.     [
  5015.         0,1,1,1,1,1,1,0,
  5016.         0,0,1,0,0,1,0,0,
  5017.         0,0,1,0,0,1,0,0,
  5018.         0,0,0,1,1,0,0,0,
  5019.         0,0,0,1,1,0,0,0,
  5020.         0,0,1,1,1,1,0,0,
  5021.         0,0,1,1,1,1,0,0,
  5022.         0,1,1,1,1,1,1,0,
  5023.     ],
  5024.     [
  5025.         0,0,0,0,0,0,0,0,
  5026.         1,0,0,0,0,0,0,1,
  5027.         1,1,1,0,0,1,1,1,
  5028.         1,1,1,1,1,0,0,1,
  5029.         1,1,1,1,1,0,0,1,
  5030.         1,1,1,0,0,1,1,1,
  5031.         1,0,0,0,0,0,0,1,
  5032.         0,0,0,0,0,0,0,0,
  5033.     ]
  5034. ];
  5035. var loading_anim_frame = 0;
  5036. var loading_anim_speed = 500;
  5037. var loading_interval = null;
  5038.  
  5039. function loadingAnimation() {
  5040.     //create image
  5041.     var loadingAnimImg = ctx.createImageData(8*scale, 8*scale);
  5042.     //draw image
  5043.     for (var y = 0; y < 8; y++) {
  5044.         for (var x = 0; x < 8; x++) {
  5045.             var i = (y * 8) + x;
  5046.             if (loading_anim_data[loading_anim_frame][i] == 1) {
  5047.                 //scaling nonsense
  5048.                 for (var sy = 0; sy < scale; sy++) {
  5049.                     for (var sx = 0; sx < scale; sx++) {
  5050.                         var pxl = 4 * ( (((y*scale)+sy) * (8*scale)) + ((x*scale)+sx) );
  5051.                         loadingAnimImg.data[pxl+0] = 255;
  5052.                         loadingAnimImg.data[pxl+1] = 255;
  5053.                         loadingAnimImg.data[pxl+2] = 255;
  5054.                         loadingAnimImg.data[pxl+3] = 255;
  5055.                     }
  5056.                 }
  5057.             }
  5058.         }
  5059.     }
  5060.     //put image on canvas
  5061.     ctx.putImageData(loadingAnimImg,scale*(width/2 - 4),scale*(height/2 - 4));
  5062.     //update frame
  5063.     loading_anim_frame++;
  5064.     if (loading_anim_frame >= 5) loading_anim_frame = 0;
  5065. }
  5066.  
  5067. function update() {
  5068.     var curTime = Date.now();
  5069.     deltaTime = curTime - prevTime;
  5070.  
  5071.     //clear screen
  5072.     ctx.fillStyle = "rgb(" + getPal(curPal())[0][0] + "," + getPal(curPal())[0][1] + "," + getPal(curPal())[0][2] + ")";
  5073.     ctx.fillRect(0,0,canvas.width,canvas.height);
  5074.    
  5075.     if (!isNarrating && !isEnding) {
  5076.         updateAnimation();
  5077.         drawRoom( room[curRoom] ); // draw world if game has begun
  5078.     }
  5079.  
  5080.     // if (isDialogMode) { // dialog mode
  5081.     if(dialogBuffer.IsActive()) {
  5082.         dialogRenderer.Draw( dialogBuffer, deltaTime );
  5083.         dialogBuffer.Update( deltaTime );
  5084.     }
  5085.     else if (!isEnding) {
  5086.         moveSprites();
  5087.  
  5088.         if (player().walkingPath.length > 0) {
  5089.             var dest = player().walkingPath[ player().walkingPath.length - 1 ];
  5090.             ctx.fillStyle = "#fff";
  5091.             ctx.globalAlpha = 0.5;
  5092.             ctx.fillRect( dest.x * tilesize*scale, dest.y * tilesize*scale, tilesize*scale, tilesize*scale );
  5093.             ctx.globalAlpha = 1;
  5094.         }
  5095.     }
  5096.  
  5097.     // keep moving avatar if player holds down button
  5098.     if( !dialogBuffer.IsActive() && !isEnding )
  5099.     {
  5100.         if( curPlayerDirection != Direction.None ) {
  5101.             playerHoldToMoveTimer -= deltaTime;
  5102.  
  5103.             if( playerHoldToMoveTimer <= 0 )
  5104.             {
  5105.                 movePlayer( curPlayerDirection );
  5106.                 playerHoldToMoveTimer = 150;
  5107.             }
  5108.         }
  5109.     }
  5110.  
  5111.     prevTime = curTime;
  5112.  
  5113.     //for gif recording
  5114.     if (didPlayerMoveThisFrame && onPlayerMoved != null) onPlayerMoved();
  5115.     didPlayerMoveThisFrame = false;
  5116.     // if (didDialogUpdateThisFrame && onDialogUpdate != null) onDialogUpdate();
  5117.     // didDialogUpdateThisFrame = false;
  5118.     /* hacky replacement */
  5119.     if (onDialogUpdate != null)
  5120.         dialogRenderer.SetPageFinishHandler( onDialogUpdate );
  5121. }
  5122.  
  5123. var animationCounter = 0;
  5124. var animationTime = 400;
  5125. function updateAnimation() {
  5126.     animationCounter += deltaTime;
  5127.  
  5128.     if ( animationCounter >= animationTime ) {
  5129.  
  5130.         // animate sprites
  5131.         for (id in sprite) {
  5132.             var spr = sprite[id];
  5133.             if (spr.animation.isAnimated) {
  5134.                 spr.animation.frameIndex = ( spr.animation.frameIndex + 1 ) % spr.animation.frameCount;
  5135.             }
  5136.         }
  5137.  
  5138.         // animate tiles
  5139.         for (id in tile) {
  5140.             var til = tile[id];
  5141.             if (til.animation.isAnimated) {
  5142.                 til.animation.frameIndex = ( til.animation.frameIndex + 1 ) % til.animation.frameCount;
  5143.             }
  5144.         }
  5145.  
  5146.         // animate items
  5147.         for (id in item) {
  5148.             var itm = item[id];
  5149.             if (itm.animation.isAnimated) {
  5150.                 itm.animation.frameIndex = ( itm.animation.frameIndex + 1 ) % itm.animation.frameCount;
  5151.             }
  5152.         }
  5153.  
  5154.         // reset counter
  5155.         animationCounter = 0;
  5156.  
  5157.     }
  5158. }
  5159.  
  5160. var moveCounter = 0;
  5161. var moveTime = 200;
  5162. function moveSprites() {
  5163.     moveCounter += deltaTime;
  5164.  
  5165.     if (moveCounter >= moveTime) {
  5166.  
  5167.         for (id in sprite) {
  5168.             var spr = sprite[id];
  5169.             if (spr.walkingPath.length > 0) {
  5170.                 //move sprite
  5171.                 var nextPos = spr.walkingPath.shift();
  5172.                 spr.x = nextPos.x;
  5173.                 spr.y = nextPos.y;
  5174.  
  5175.  
  5176.                 var end = getEnding( spr.room, spr.x, spr.y );
  5177.                 var ext = getExit( spr.room, spr.x, spr.y );
  5178.                 var itmIndex = getItemIndex( spr.room, spr.x, spr.y );
  5179.                 if (end) { //if the sprite hits an ending
  5180.                     if (id === playerId) { // only the player can end the game
  5181.                         startNarrating( ending[end.id], true /*isEnding*/ );
  5182.                     }
  5183.                 }
  5184.                 else if (ext) { //if the sprite hits an exit
  5185.                     //move it to another scene
  5186.                     spr.room = ext.dest.room;
  5187.                     spr.x = ext.dest.x;
  5188.                     spr.y = ext.dest.y;
  5189.                     if (id === playerId) {
  5190.                         //if the player changes scenes, change the visible scene
  5191.                         curRoom = ext.dest.room;
  5192.                     }
  5193.                 }
  5194.                 else if(itmIndex > -1) {
  5195.                     var itm = room[ spr.room ].items[ itmIndex ];
  5196.                     room[ spr.room ].items.splice( itmIndex, 1 );
  5197.                     if( spr.inventory[ itm.id ] )
  5198.                         spr.inventory[ itm.id ] += 1;
  5199.                     else
  5200.                         spr.inventory[ itm.id ] = 1;
  5201.  
  5202.                     if(onInventoryChanged != null)
  5203.                         onInventoryChanged( itm.id );
  5204.  
  5205.                     if(id === playerId)
  5206.                         startItemDialog( itm.id  /*itemId*/ );
  5207.  
  5208.                     // stop moving : is this a good idea?
  5209.                     spr.walkingPath = [];
  5210.                 }
  5211.  
  5212.                 if (id === playerId) didPlayerMoveThisFrame = true;
  5213.             }
  5214.         }
  5215.  
  5216.         moveCounter = 0;
  5217.     }
  5218.  
  5219. }
  5220.  
  5221. function getSpriteAt(x,y) {
  5222.     for (id in sprite) {
  5223.         var spr = sprite[id];
  5224.         if (spr.room === curRoom) {
  5225.             if (spr.x == x && spr.y == y) {
  5226.                 return id;
  5227.             }
  5228.         }
  5229.     }
  5230.     return null;
  5231. }
  5232.  
  5233. var Direction = {
  5234.     None : -1,
  5235.     Up : 0,
  5236.     Down : 1,
  5237.     Left : 2,
  5238.     Right : 3
  5239. };
  5240.  
  5241. var curPlayerDirection = Direction.None;
  5242. var playerHoldToMoveTimer = 0;
  5243.  
  5244. var keyDownList = [];
  5245.  
  5246. function onkeydown(e) {
  5247.     if(e.keyCode == key.left || e.keyCode == key.right || e.keyCode == key.up || e.keyCode == key.down || !isPlayerEmbeddedInEditor)
  5248.         e.preventDefault();
  5249.  
  5250.     if( keyDownList.indexOf( e.keyCode ) != -1 ) {
  5251.         // key already down --- do nothing
  5252.         return;
  5253.     }
  5254.  
  5255.     curPlayerDirection = Direction.None;
  5256.  
  5257.     if( dialogBuffer.IsActive() ) {
  5258.         /* CONTINUE DIALOG */
  5259.         if (dialogBuffer.CanContinue()) {
  5260.             var hasMoreDialog = dialogBuffer.Continue();
  5261.             if(!hasMoreDialog) {
  5262.                 console.log("EXIT DIALOG --- onkeydown")
  5263.                 onExitDialog();
  5264.             }
  5265.         }
  5266.         else {
  5267.             dialogBuffer.Skip();
  5268.         }
  5269.     }
  5270.     else if ( isEnding ) {
  5271.         /* RESTART GAME */
  5272.         reset_cur_game();
  5273.     }
  5274.     else {
  5275.         /* WALK */
  5276.         if ( e.keyCode == key.left || e.keyCode == key.a ) {
  5277.             curPlayerDirection = Direction.Left;
  5278.         }
  5279.         else if ( e.keyCode == key.right || e.keyCode == key.d ) {
  5280.             curPlayerDirection = Direction.Right;
  5281.         }
  5282.         else if ( e.keyCode == key.up || e.keyCode == key.w ) {
  5283.             curPlayerDirection = Direction.Up;
  5284.         }
  5285.         else if ( e.keyCode == key.down || e.keyCode == key.s ) {
  5286.             curPlayerDirection = Direction.Down;
  5287.         }
  5288.         movePlayer( curPlayerDirection );
  5289.  
  5290.         if( curPlayerDirection != Direction.None )
  5291.         {
  5292.             playerHoldToMoveTimer = 500;
  5293.         }
  5294.  
  5295.         /* RESTART GAME */
  5296.         if ( e.keyCode === key.r && ( e.getModifierState("Control") || e.getModifierState("Meta") ) ) {
  5297.             if ( confirm("Restart the game?") ) {
  5298.                 reset_cur_game();
  5299.             }
  5300.         }
  5301.     }
  5302.  
  5303.     if( keyDownList.indexOf( e.keyCode ) == -1 )
  5304.         keyDownList.push( e.keyCode );
  5305.  
  5306.     console.log("KEY DOWN " + keyDownList.length );
  5307.     console.log(keyDownList);
  5308. }
  5309.  
  5310. function movePlayer(direction) {
  5311.     var spr = null;
  5312.  
  5313.     if ( curPlayerDirection == Direction.Left && !(spr = getSpriteLeft()) && !isWallLeft()) {
  5314.         player().x -= 1;
  5315.         didPlayerMoveThisFrame = true;
  5316.     }
  5317.     else if ( curPlayerDirection == Direction.Right && !(spr = getSpriteRight()) && !isWallRight()) {
  5318.         player().x += 1;
  5319.         didPlayerMoveThisFrame = true;
  5320.     }
  5321.     else if ( curPlayerDirection == Direction.Up && !(spr = getSpriteUp()) && !isWallUp()) {
  5322.         player().y -= 1;
  5323.         didPlayerMoveThisFrame = true;
  5324.     }
  5325.     else if ( curPlayerDirection == Direction.Down && !(spr = getSpriteDown()) && !isWallDown()) {
  5326.         player().y += 1;
  5327.         didPlayerMoveThisFrame = true;
  5328.     }
  5329.    
  5330.     var ext = getExit( player().room, player().x, player().y );
  5331.     var end = getEnding( player().room, player().x, player().y );
  5332.     var itmIndex = getItemIndex( player().room, player().x, player().y );
  5333.  
  5334.     // do items first, because you can pick up an item AND go through a door
  5335.     if (itmIndex > -1) {
  5336.         // TODO pick up items (what about touch?)
  5337.         // console.log("HIT ITM ");
  5338.         // console.log( itmIndex );
  5339.         var itm = room[ player().room ].items[ itmIndex ];
  5340.         // console.log(itm);
  5341.         room[ player().room ].items.splice( itmIndex, 1 );
  5342.         if( player().inventory[ itm.id ] )
  5343.             player().inventory[ itm.id ] += 1;
  5344.         else
  5345.             player().inventory[ itm.id ] = 1;
  5346.  
  5347.         if(onInventoryChanged != null)
  5348.             onInventoryChanged( itm.id );
  5349.  
  5350.         startItemDialog( itm.id  /*itemId*/ );
  5351.  
  5352.         // console.log( player().inventory );
  5353.     }
  5354.  
  5355.     if (end) {
  5356.         startNarrating( ending[end.id], true /*isEnding*/ );
  5357.     }
  5358.     else if (ext) {
  5359.         player().room = ext.dest.room;
  5360.         player().x = ext.dest.x;
  5361.         player().y = ext.dest.y;
  5362.         curRoom = ext.dest.room;
  5363.     }
  5364.     else if (spr) {
  5365.         startSpriteDialog( spr /*spriteId*/ );
  5366.     }
  5367. }
  5368.  
  5369. function onkeyup(e) {
  5370.  
  5371.     if(e.keyCode == key.left || e.keyCode == key.right || e.keyCode == key.up || e.keyCode == key.down || !isPlayerEmbeddedInEditor)
  5372.         e.preventDefault();
  5373.  
  5374.     if( keyDownList.indexOf( e.keyCode ) != -1 )
  5375.         keyDownList.splice( keyDownList.indexOf( e.keyCode ), 1 );
  5376.  
  5377.     // todo is this robust enough?
  5378.     if( keyDownList.length <= 0 )
  5379.         curPlayerDirection = Direction.None;
  5380.  
  5381.     console.log(e.keyCode);
  5382.     console.log("KEY UP " + keyDownList.length );
  5383.     console.log(keyDownList);
  5384.     console.log("_____");
  5385. }
  5386.  
  5387. var touchInfo = {
  5388.     isDown : false,
  5389.     startX : 0,
  5390.     startY : 0,
  5391.     curX : 0,
  5392.     curY : 0
  5393. };
  5394.  
  5395. function ontouchstart(e) {
  5396.     e.preventDefault();
  5397.  
  5398.     if( e.changedTouches.length > 0 ) {
  5399.         touchInfo.isDown = true;
  5400.  
  5401.         console.log(e);
  5402.  
  5403.         touchInfo.startX = touchInfo.curX = e.changedTouches[0].clientX;
  5404.         touchInfo.startY = touchInfo.curY = e.changedTouches[0].clientY;
  5405.  
  5406.         console.log("MOUSE DOWN");
  5407.         console.log(touchInfo);
  5408.  
  5409.         curPlayerDirection = Direction.None;
  5410.     }
  5411. }
  5412.  
  5413. var swipeDistance = 30;
  5414. function ontouchmove(e) {
  5415.     e.preventDefault();
  5416.  
  5417.     console.log("MOUSE MOVE");
  5418.     console.log(touchInfo);
  5419.  
  5420.     if( !dialogBuffer.IsActive() && touchInfo.isDown && e.changedTouches.length > 0 ) {
  5421.         touchInfo.curX = e.changedTouches[0].clientX;
  5422.         touchInfo.curY = e.changedTouches[0].clientY;
  5423.  
  5424.         var prevDirection = curPlayerDirection;
  5425.  
  5426.         console.log( touchInfo.curX - touchInfo.startX );
  5427.  
  5428.         if( touchInfo.curX - touchInfo.startX <= -swipeDistance ) {
  5429.             curPlayerDirection = Direction.Left;
  5430.         }
  5431.         else if( touchInfo.curX - touchInfo.startX >= swipeDistance ) {
  5432.             curPlayerDirection = Direction.Right;
  5433.         }
  5434.         else if( touchInfo.curY - touchInfo.startY <= -swipeDistance ) {
  5435.             curPlayerDirection = Direction.Up;
  5436.         }
  5437.         else if( touchInfo.curY - touchInfo.startY >= swipeDistance ) {
  5438.             curPlayerDirection = Direction.Down;
  5439.         }
  5440.  
  5441.         if( curPlayerDirection != prevDirection ) {
  5442.             movePlayer( curPlayerDirection );
  5443.             playerHoldToMoveTimer = 300;
  5444.             // reset center
  5445.             touchInfo.startX = touchInfo.curX;
  5446.             touchInfo.startY = touchInfo.curY;
  5447.         }
  5448.     }
  5449. }
  5450.  
  5451. function ontouchend(e) {
  5452.     e.preventDefault();
  5453.  
  5454.     console.log("MOUSE UP");
  5455.     console.log(touchInfo);
  5456.  
  5457.     touchInfo.isDown = false;
  5458.  
  5459.     if( curPlayerDirection == Direction.None ) {
  5460.         // tap!
  5461.         if( dialogBuffer.IsActive() ) {
  5462.             /* CONTINUE DIALOG */
  5463.             if (dialogBuffer.CanContinue()) {
  5464.                 var hasMoreDialog = dialogBuffer.Continue();
  5465.                 if(!hasMoreDialog) {
  5466.                     console.log("EXIT DIALOG --- onkeydown")
  5467.                     onExitDialog();
  5468.                 }
  5469.             }
  5470.             else {
  5471.                 dialogBuffer.Skip();
  5472.             }
  5473.         }
  5474.         else if ( isEnding ) {
  5475.             /* RESTART GAME */
  5476.             reset_cur_game();
  5477.         }
  5478.     }
  5479.  
  5480.     curPlayerDirection = Direction.None;
  5481. }
  5482.  
  5483. function getItemIndex( roomId, x, y ) {
  5484.     for( var i = 0; i < room[roomId].items.length; i++ ) {
  5485.         var itm = room[roomId].items[i];
  5486.         if ( itm.x == x && itm.y == y)
  5487.             return i;
  5488.     }
  5489.     return -1;
  5490. }
  5491.  
  5492. function getSpriteLeft() { //repetitive?
  5493.     return getSpriteAt( player().x - 1, player().y );
  5494. }
  5495.  
  5496. function getSpriteRight() {
  5497.     return getSpriteAt( player().x + 1, player().y );
  5498. }
  5499.  
  5500. function getSpriteUp() {
  5501.     return getSpriteAt( player().x, player().y - 1 );
  5502. }
  5503.  
  5504. function getSpriteDown() {
  5505.     return getSpriteAt( player().x, player().y + 1 );
  5506. }
  5507.  
  5508. function isWallLeft() {
  5509.     return (player().x - 1 < 0) || isWall( player().x - 1, player().y );
  5510. }
  5511.  
  5512. function isWallRight() {
  5513.     return (player().x + 1 >= 16) || isWall( player().x + 1, player().y );
  5514. }
  5515.  
  5516. function isWallUp() {
  5517.     return (player().y - 1 < 0) || isWall( player().x, player().y - 1 );
  5518. }
  5519.  
  5520. function isWallDown() {
  5521.     return (player().y + 1 >= 16) || isWall( player().x, player().y + 1 );
  5522. }
  5523.  
  5524. function isWall(x,y,roomId) {
  5525.     if(roomId == undefined || roomId == null)
  5526.         roomId = curRoom;
  5527.  
  5528.     var tileId = getTile( x, y );
  5529.  
  5530.     if( tileId === '0' )
  5531.         return false; // Blank spaces aren't walls, ya doofus
  5532.  
  5533.     if( tile[tileId].isWall === undefined || tile[tileId].isWall === null ) {
  5534.         // No wall-state defined: check room-specific walls
  5535.         var i = room[roomId].walls.indexOf( getTile(x,y) );
  5536.         return i > -1;
  5537.     }
  5538.  
  5539.     // Otherwise, use the tile's own wall-state
  5540.     return tile[tileId].isWall;
  5541. }
  5542.  
  5543. function getItem(roomId,x,y) {
  5544.     for (i in room[roomId].items) {
  5545.         var item = room[roomId].items[i];
  5546.         if (x == item.x && y == item.y) {
  5547.             return item;
  5548.         }
  5549.     }
  5550.     return null;
  5551. }
  5552.  
  5553. function getExit(roomId,x,y) {
  5554.     for (i in room[roomId].exits) {
  5555.         var e = room[roomId].exits[i];
  5556.         if (x == e.x && y == e.y) {
  5557.             return e;
  5558.         }
  5559.     }
  5560.     return null;
  5561. }
  5562.  
  5563. function getEnding(roomId,x,y) {
  5564.     for (i in room[roomId].endings) {
  5565.         var e = room[roomId].endings[i];
  5566.         if (x == e.x && y == e.y) {
  5567.             return e;
  5568.         }
  5569.     }
  5570.     return null;
  5571. }
  5572.  
  5573. function getTile(x,y) {
  5574.     // console.log(x + " " + y);
  5575.     var t = getRoom().tilemap[y][x];
  5576.     return t;
  5577. }
  5578.  
  5579. function player() {
  5580.     return sprite[playerId];
  5581. }
  5582.  
  5583. // Sort of a hack for legacy palette code (when it was just an array)
  5584. function getPal(id) {
  5585.     return palette[ id ].colors;
  5586. }
  5587.  
  5588. function getRoom() {
  5589.     return room[curRoom];
  5590. }
  5591.  
  5592. function isSpriteOffstage(id) {
  5593.     return sprite[id].room == null;
  5594. }
  5595.  
  5596. function parseWorld(file) {
  5597.     resetFlags();
  5598.  
  5599.     var lines = file.split("\n");
  5600.     var i = 0;
  5601.     while (i < lines.length) {
  5602.         var curLine = lines[i];
  5603.  
  5604.         // console.log(lines[i]);
  5605.  
  5606.         if (i == 0) {
  5607.             i = parseTitle(lines, i);
  5608.         }
  5609.         else if (curLine.length <= 0 || curLine.charAt(0) === "#") {
  5610.             //skip blank lines & comments
  5611.             i++;
  5612.         }
  5613.         else if (getType(curLine) == "PAL") {
  5614.             i = parsePalette(lines, i);
  5615.         }
  5616.         else if (getType(curLine) === "ROOM" || getType(curLine) === "SET") { //SET for back compat
  5617.             i = parseRoom(lines, i);
  5618.         }
  5619.         else if (getType(curLine) === "TIL") {
  5620.             i = parseTile(lines, i);
  5621.         }
  5622.         else if (getType(curLine) === "SPR") {
  5623.             i = parseSprite(lines, i);
  5624.         }
  5625.         else if (getType(curLine) === "ITM") {
  5626.             i = parseItem(lines, i);
  5627.         }
  5628.         else if (getType(curLine) === "DRW") {
  5629.             i = parseDrawing(lines, i);
  5630.         }
  5631.         else if (getType(curLine) === "DLG") {
  5632.             i = parseDialog(lines, i);
  5633.         }
  5634.         else if (getType(curLine) === "END") {
  5635.             i = parseEnding(lines, i);
  5636.         }
  5637.         else if (getType(curLine) === "VAR") {
  5638.             i = parseVariable(lines, i);
  5639.         }
  5640.         else if (getType(curLine) === "!") {
  5641.             i = parseFlag(lines, i);
  5642.         }
  5643.         else {
  5644.             i++;
  5645.         }
  5646.     }
  5647.     placeSprites();
  5648.     if (player().room != null) {
  5649.         curRoom = player().room;
  5650.     }
  5651.  
  5652.     console.log(names);
  5653. }
  5654.  
  5655. //TODO this is in progress and doesn't support all features
  5656. function serializeWorld() {
  5657.     var worldStr = "";
  5658.     /* TITLE */
  5659.     worldStr += title + "\n";
  5660.     worldStr += "\n";
  5661.     /* VERSION */
  5662.     worldStr += "# BITSY VERSION " + getEngineVersion() + "\n"; // add version as a comment for debugging purposes
  5663.     worldStr += "\n";
  5664.     /* FLAGS */
  5665.     for (f in flags) {
  5666.         worldStr += "! " + f + " " + flags[f] + "\n";
  5667.     }
  5668.     worldStr += "\n"
  5669.     /* PALETTE */
  5670.     for (id in palette) {
  5671.         worldStr += "PAL " + id + "\n";
  5672.         if( palette[id].name != null )
  5673.             worldStr += "NAME " + palette[id].name + "\n";
  5674.         for (i in getPal(id)) {
  5675.             for (j in getPal(id)[i]) {
  5676.                 worldStr += getPal(id)[i][j];
  5677.                 if (j < 2) worldStr += ",";
  5678.             }
  5679.             worldStr += "\n";
  5680.         }
  5681.         worldStr += "\n";
  5682.     }
  5683.     /* ROOM */
  5684.     for (id in room) {
  5685.         worldStr += "ROOM " + id + "\n";
  5686.         if ( flags.ROOM_FORMAT == 0 ) {
  5687.             // old non-comma separated format
  5688.             for (i in room[id].tilemap) {
  5689.                 for (j in room[id].tilemap[i]) {
  5690.                     worldStr += room[id].tilemap[i][j];
  5691.                 }
  5692.                 worldStr += "\n";
  5693.             }
  5694.         }
  5695.         else if ( flags.ROOM_FORMAT == 1 ) {
  5696.             // new comma separated format
  5697.             for (i in room[id].tilemap) {
  5698.                 for (j in room[id].tilemap[i]) {
  5699.                     worldStr += room[id].tilemap[i][j];
  5700.                     if (j < room[id].tilemap[i].length-1) worldStr += ","
  5701.                 }
  5702.                 worldStr += "\n";
  5703.             }
  5704.         }
  5705.         if (room[id].name != null) {
  5706.             /* NAME */
  5707.             worldStr += "NAME " + room[id].name + "\n";
  5708.         }
  5709.         if (room[id].walls.length > 0) {
  5710.             /* WALLS */
  5711.             worldStr += "WAL ";
  5712.             for (j in room[id].walls) {
  5713.                 worldStr += room[id].walls[j];
  5714.                 if (j < room[id].walls.length-1) {
  5715.                     worldStr += ",";
  5716.                 }
  5717.             }
  5718.             worldStr += "\n";
  5719.         }
  5720.         if (room[id].items.length > 0) {
  5721.             /* ITEMS */
  5722.             for (j in room[id].items) {
  5723.                 var itm = room[id].items[j];
  5724.                 worldStr += "ITM " + itm.id + " " + itm.x + "," + itm.y;
  5725.                 worldStr += "\n";
  5726.             }
  5727.         }
  5728.         if (room[id].exits.length > 0) {
  5729.             /* EXITS */
  5730.             for (j in room[id].exits) {
  5731.                 var e = room[id].exits[j];
  5732.                 if ( isExitValid(e) ) {
  5733.                     worldStr += "EXT " + e.x + "," + e.y + " " + e.dest.room + " " + e.dest.x + "," + e.dest.y;
  5734.                     worldStr += "\n";
  5735.                 }
  5736.             }
  5737.         }
  5738.         if (room[id].endings.length > 0) {
  5739.             /* ENDINGS */
  5740.             for (j in room[id].endings) {
  5741.                 var e = room[id].endings[j];
  5742.                 // todo isEndingValid
  5743.                 worldStr += "END " + e.id + " " + e.x + "," + e.y;
  5744.                 worldStr += "\n";
  5745.             }
  5746.         }
  5747.         if (room[id].pal != null) {
  5748.             /* PALETTE */
  5749.             worldStr += "PAL " + room[id].pal + "\n";
  5750.         }
  5751.         worldStr += "\n";
  5752.     }
  5753.     /* TILES */
  5754.     for (id in tile) {
  5755.         worldStr += "TIL " + id + "\n";
  5756.         worldStr += serializeDrawing( "TIL_" + id );
  5757.         if (tile[id].name != null && tile[id].name != undefined) {
  5758.             /* NAME */
  5759.             worldStr += "NAME " + tile[id].name + "\n";
  5760.         }
  5761.         if (tile[id].isWall != null && tile[id].isWall != undefined) {
  5762.             /* WALL */
  5763.             worldStr += "WAL " + tile[id].isWall + "\n";
  5764.         }
  5765.         if (tile[id].col != null && tile[id].col != undefined && tile[id].col != 1) {
  5766.             /* COLOR OVERRIDE */
  5767.             worldStr += "COL " + tile[id].col + "\n";
  5768.         }
  5769.         worldStr += "\n";
  5770.     }
  5771.     /* SPRITES */
  5772.     for (id in sprite) {
  5773.         worldStr += "SPR " + id + "\n";
  5774.         worldStr += serializeDrawing( "SPR_" + id );
  5775.         if (sprite[id].name != null && sprite[id].name != undefined) {
  5776.             /* NAME */
  5777.             worldStr += "NAME " + sprite[id].name + "\n";
  5778.         }
  5779.         if (sprite[id].dlg != null) {
  5780.             worldStr += "DLG " + sprite[id].dlg + "\n";
  5781.         }
  5782.         if (sprite[id].room != null) {
  5783.             /* SPRITE POSITION */
  5784.             worldStr += "POS " + sprite[id].room + " " + sprite[id].x + "," + sprite[id].y + "\n";
  5785.         }
  5786.         if (sprite[id].inventory != null) {
  5787.             for(itemId in sprite[id].inventory) {
  5788.                 worldStr += "ITM " + itemId + " " + sprite[id].inventory[itemId] + "\n";
  5789.             }
  5790.         }
  5791.         if (sprite[id].col != null && sprite[id].col != undefined && sprite[id].col != 2) {
  5792.             /* COLOR OVERRIDE */
  5793.             worldStr += "COL " + sprite[id].col + "\n";
  5794.         }
  5795.         worldStr += "\n";
  5796.     }
  5797.     /* ITEMS */
  5798.     for (id in item) {
  5799.         worldStr += "ITM " + id + "\n";
  5800.         worldStr += serializeDrawing( "ITM_" + id );
  5801.         if (item[id].name != null && item[id].name != undefined) {
  5802.             /* NAME */
  5803.             worldStr += "NAME " + item[id].name + "\n";
  5804.         }
  5805.         if (item[id].dlg != null) {
  5806.             worldStr += "DLG " + item[id].dlg + "\n";
  5807.         }
  5808.         if (item[id].col != null && item[id].col != undefined && item[id].col != 2) {
  5809.             /* COLOR OVERRIDE */
  5810.             worldStr += "COL " + item[id].col + "\n";
  5811.         }
  5812.         worldStr += "\n";
  5813.     }
  5814.     /* DIALOG */
  5815.     for (id in dialog) {
  5816.         worldStr += "DLG " + id + "\n";
  5817.         worldStr += dialog[id] + "\n";
  5818.         worldStr += "\n";
  5819.     }
  5820.     /* ENDINGS */
  5821.     for (id in ending) {
  5822.         worldStr += "END " + id + "\n";
  5823.         worldStr += ending[id] + "\n";
  5824.         worldStr += "\n";
  5825.     }
  5826.     /* VARIABLES */
  5827.     for (id in variable) {
  5828.         worldStr += "VAR " + id + "\n";
  5829.         worldStr += variable[id] + "\n";
  5830.         worldStr += "\n";
  5831.     }
  5832.     return worldStr;
  5833. }
  5834.  
  5835. function serializeDrawing(drwId) {
  5836.     var drwStr = "";
  5837.     for (f in imageStore.source[drwId]) {
  5838.         for (y in imageStore.source[drwId][f]) {
  5839.             var rowStr = "";
  5840.             for (x in imageStore.source[drwId][f][y]) {
  5841.                 rowStr += imageStore.source[drwId][f][y][x];
  5842.             }
  5843.             drwStr += rowStr + "\n";
  5844.         }
  5845.         if (f < (imageStore.source[drwId].length-1)) drwStr += ">\n";
  5846.     }
  5847.     return drwStr;
  5848. }
  5849.  
  5850. function isExitValid(e) {
  5851.     var hasValidStartPos = e.x >= 0 && e.x < 16 && e.y >= 0 && e.y < 16;
  5852.     var hasDest = e.dest != null;
  5853.     var hasValidRoomDest = (e.dest.room != null && e.dest.x >= 0 && e.dest.x < 16 && e.dest.y >= 0 && e.dest.y < 16);
  5854.     return hasValidStartPos && hasDest && hasValidRoomDest;
  5855. }
  5856.  
  5857. function placeSprites() {
  5858.     for (id in spriteStartLocations) {
  5859.         //console.log(id);
  5860.         //console.log( spriteStartLocations[id] );
  5861.         //console.log(sprite[id]);
  5862.         sprite[id].room = spriteStartLocations[id].room;
  5863.         sprite[id].x = spriteStartLocations[id].x;
  5864.         sprite[id].y = spriteStartLocations[id].y;
  5865.         //console.log(sprite[id]);
  5866.     }
  5867. }
  5868.  
  5869. /* ARGUMENT GETTERS */
  5870. function getType(line) {
  5871.     return getArg(line,0);
  5872. }
  5873.  
  5874. function getId(line) {
  5875.     return getArg(line,1);
  5876. }
  5877.  
  5878. function getArg(line,arg) {
  5879.     return line.split(" ")[arg];
  5880. }
  5881.  
  5882. function getCoord(line,arg) {
  5883.     return getArg(line,arg).split(",");
  5884. }
  5885.  
  5886. function parseTitle(lines, i) {
  5887.     title = lines[i];
  5888.     i++;
  5889.     return i;
  5890. }
  5891.  
  5892. function parseRoom(lines, i) {
  5893.     var id = getId(lines[i]);
  5894.     room[id] = {
  5895.         id : id,
  5896.         tilemap : [],
  5897.         walls : [],
  5898.         exits : [],
  5899.         endings : [],
  5900.         items : [],
  5901.         pal : null,
  5902.         name : null
  5903.     };
  5904.     i++;
  5905.  
  5906.     // create tile map
  5907.     if ( flags.ROOM_FORMAT == 0 ) {
  5908.         // old way: no commas, single char tile ids
  5909.         var end = i + mapsize;
  5910.         var y = 0;
  5911.         for (; i<end; i++) {
  5912.             room[id].tilemap.push( [] );
  5913.             for (x = 0; x<mapsize; x++) {
  5914.                 room[id].tilemap[y].push( lines[i].charAt(x) );
  5915.             }
  5916.             y++;
  5917.         }
  5918.     }
  5919.     else if ( flags.ROOM_FORMAT == 1 ) {
  5920.         // new way: comma separated, multiple char tile ids
  5921.         var end = i + mapsize;
  5922.         var y = 0;
  5923.         for (; i<end; i++) {
  5924.             room[id].tilemap.push( [] );
  5925.             var lineSep = lines[i].split(",");
  5926.             for (x = 0; x<mapsize; x++) {
  5927.                 room[id].tilemap[y].push( lineSep[x] );
  5928.             }
  5929.             y++;
  5930.         }
  5931.     }
  5932.  
  5933.     while (i < lines.length && lines[i].length > 0) { //look for empty line
  5934.         // console.log(getType(lines[i]));
  5935.         if (getType(lines[i]) === "SPR") {
  5936.             /* NOTE SPRITE START LOCATIONS */
  5937.             var sprId = getId(lines[i]);
  5938.             if (sprId.indexOf(",") == -1 && lines[i].split(" ").length >= 3) { //second conditional checks for coords
  5939.                 /* PLACE A SINGLE SPRITE */
  5940.                 var sprCoord = lines[i].split(" ")[2].split(",");
  5941.                 spriteStartLocations[sprId] = {
  5942.                     room : id,
  5943.                     x : parseInt(sprCoord[0]),
  5944.                     y : parseInt(sprCoord[1])
  5945.                 };
  5946.             }
  5947.             else if ( flags.ROOM_FORMAT == 0 ) { // TODO: right now this shortcut only works w/ the old comma separate format
  5948.                 /* PLACE MULTIPLE SPRITES*/
  5949.                 //Does find and replace in the tilemap (may be hacky, but its convenient)
  5950.                 var sprList = sprId.split(",");
  5951.                 for (row in room[id].tilemap) {
  5952.                     for (s in sprList) {
  5953.                         var col = room[id].tilemap[row].indexOf( sprList[s] );
  5954.                         //if the sprite is in this row, replace it with the "null tile" and set its starting position
  5955.                         if (col != -1) {
  5956.                             room[id].tilemap[row][col] = "0";
  5957.                             spriteStartLocations[ sprList[s] ] = {
  5958.                                 room : id,
  5959.                                 x : parseInt(col),
  5960.                                 y : parseInt(row)
  5961.                             };
  5962.                         }
  5963.                     }
  5964.                 }
  5965.             }
  5966.         }
  5967.         else if (getType(lines[i]) === "ITM") {
  5968.             var itmId = getId(lines[i]);
  5969.             var itmCoord = lines[i].split(" ")[2].split(",");
  5970.             var itm = {
  5971.                 id: itmId,
  5972.                 x : parseInt(itmCoord[0]),
  5973.                 y : parseInt(itmCoord[1])
  5974.             };
  5975.             room[id].items.push( itm );
  5976.         }
  5977.         else if (getType(lines[i]) === "WAL") {
  5978.             /* DEFINE COLLISIONS (WALLS) */
  5979.             room[id].walls = getId(lines[i]).split(",");
  5980.         }
  5981.         else if (getType(lines[i]) === "EXT") {
  5982.             /* ADD EXIT */
  5983.             var exitArgs = lines[i].split(" ");
  5984.             //arg format: EXT 10,5 M 3,2 [AVA:7 LCK:a,9] [AVA 7 LCK a 9]
  5985.             var exitCoords = exitArgs[1].split(",");
  5986.             var destName = exitArgs[2];
  5987.             var destCoords = exitArgs[3].split(",");
  5988.             var ext = {
  5989.                 x : parseInt(exitCoords[0]),
  5990.                 y : parseInt(exitCoords[1]),
  5991.                 dest : {
  5992.                     room : destName,
  5993.                     x : parseInt(destCoords[0]),
  5994.                     y : parseInt(destCoords[1])
  5995.                 }
  5996.             };
  5997.             room[id].exits.push(ext);
  5998.         }
  5999.         else if (getType(lines[i]) === "END") {
  6000.             /* ADD ENDING */
  6001.             var endId = getId( lines[i] );
  6002.             var endCoords = getCoord( lines[i], 2 );
  6003.             var end = {
  6004.                 id : endId,
  6005.                 x : parseInt( endCoords[0] ),
  6006.                 y : parseInt( endCoords[1] )
  6007.             };
  6008.             room[id].endings.push(end);
  6009.         }
  6010.         else if (getType(lines[i]) === "PAL") {
  6011.             /* CHOOSE PALETTE (that's not default) */
  6012.             room[id].pal = getId(lines[i]);
  6013.         }
  6014.         else if (getType(lines[i]) === "NAME") {
  6015.             var name = lines[i].split(/\s(.+)/)[1];
  6016.             room[id].name = name;
  6017.             names.room.set( name, id);
  6018.         }
  6019.         i++;
  6020.     }
  6021.     return i;
  6022. }
  6023.  
  6024. function parsePalette(lines,i) { //todo this has to go first right now :(
  6025.     var id = getId(lines[i]);
  6026.     i++;
  6027.     var colors = [];
  6028.     var name = null;
  6029.     while (i < lines.length && lines[i].length > 0) { //look for empty line
  6030.         var args = lines[i].split(" ");
  6031.         if(args[0] === "NAME") {
  6032.             name = lines[i].split(/\s(.+)/)[1];
  6033.         }
  6034.         else {
  6035.             var col = [];
  6036.             lines[i].split(",").forEach(function(i) {
  6037.                 col.push(parseInt(i));
  6038.             });
  6039.             colors.push(col);
  6040.         }
  6041.         i++;
  6042.     }
  6043.     palette[id] = {
  6044.         name : name,
  6045.         colors : colors
  6046.     };
  6047.     return i;
  6048. }
  6049.  
  6050. function parseTile(lines, i) {
  6051.     var id = getId(lines[i]);
  6052.     var drwId = null;
  6053.     var name = null;
  6054.  
  6055.     i++;
  6056.  
  6057.     if (getType(lines[i]) === "DRW") { //load existing drawing
  6058.         drwId = getId(lines[i]);
  6059.         i++;
  6060.     }
  6061.     else {
  6062.         // store tile source
  6063.         drwId = "TIL_" + id;
  6064.         i = parseDrawingCore( lines, i, drwId );
  6065.     }
  6066.  
  6067.     //other properties
  6068.     var colorIndex = 1; // default palette color index is 1
  6069.     var isWall = null; // null indicates it can vary from room to room (original version)
  6070.     while (i < lines.length && lines[i].length > 0) { //look for empty line
  6071.         if (getType(lines[i]) === "COL") {
  6072.             colorIndex = parseInt( getId(lines[i]) );
  6073.         }
  6074.         else if (getType(lines[i]) === "NAME") {
  6075.             /* NAME */
  6076.             name = lines[i].split(/\s(.+)/)[1];
  6077.             names.tile.set( name, id );
  6078.         }
  6079.         else if (getType(lines[i]) === "WAL") {
  6080.             var wallArg = getArg( lines[i], 1 );
  6081.             if( wallArg === "true" ) {
  6082.                 isWall = true;
  6083.             }
  6084.             else if( wallArg === "false" ) {
  6085.                 isWall = false;
  6086.             }
  6087.         }
  6088.         i++;
  6089.     }
  6090.  
  6091.     //tile data
  6092.     tile[id] = {
  6093.         drw : drwId, //drawing id
  6094.         col : colorIndex,
  6095.         animation : {
  6096.             isAnimated : (imageStore.source[drwId].length > 1),
  6097.             frameIndex : 0,
  6098.             frameCount : imageStore.source[drwId].length
  6099.         },
  6100.         name : name,
  6101.         isWall : isWall
  6102.     };
  6103.  
  6104.     return i;
  6105. }
  6106.  
  6107. function parseSprite(lines, i) {
  6108.     var id = getId(lines[i]);
  6109.     var drwId = null;
  6110.     var name = null;
  6111.  
  6112.     i++;
  6113.  
  6114.     if (getType(lines[i]) === "DRW") { //load existing drawing
  6115.         drwId = getId(lines[i]);
  6116.         i++;
  6117.     }
  6118.     else {
  6119.         // store sprite source
  6120.         drwId = "SPR_" + id;
  6121.         i = parseDrawingCore( lines, i, drwId );
  6122.     }
  6123.  
  6124.     //other properties
  6125.     var colorIndex = 2; //default palette color index is 2
  6126.     var dialogId = null;
  6127.     var startingInventory = {};
  6128.     while (i < lines.length && lines[i].length > 0) { //look for empty line
  6129.         if (getType(lines[i]) === "COL") {
  6130.             /* COLOR OFFSET INDEX */
  6131.             colorIndex = parseInt( getId(lines[i]) );
  6132.         }
  6133.         else if (getType(lines[i]) === "POS") {
  6134.             /* STARTING POSITION */
  6135.             var posArgs = lines[i].split(" ");
  6136.             var roomId = posArgs[1];
  6137.             var coordArgs = posArgs[2].split(",");
  6138.             spriteStartLocations[id] = {
  6139.                 room : roomId,
  6140.                 x : parseInt(coordArgs[0]),
  6141.                 y : parseInt(coordArgs[1])
  6142.             };
  6143.         }
  6144.         else if(getType(lines[i]) === "DLG") {
  6145.             dialogId = getId(lines[i]);
  6146.         }
  6147.         else if (getType(lines[i]) === "NAME") {
  6148.             /* NAME */
  6149.             name = lines[i].split(/\s(.+)/)[1];
  6150.             names.sprite.set( name, id );
  6151.         }
  6152.         else if (getType(lines[i]) === "ITM") {
  6153.             /* ITEM STARTING INVENTORY */
  6154.             var itemId = getId(lines[i]);
  6155.             var itemCount = parseFloat( getArg(lines[i], 2) );
  6156.             startingInventory[itemId] = itemCount;
  6157.         }
  6158.         i++;
  6159.     }
  6160.  
  6161.     //sprite data
  6162.     sprite[id] = {
  6163.         drw : drwId, //drawing id
  6164.         col : colorIndex,
  6165.         dlg : dialogId,
  6166.         room : null, //default location is "offstage"
  6167.         x : -1,
  6168.         y : -1,
  6169.         walkingPath : [], //tile by tile movement path (isn't saved)
  6170.         animation : {
  6171.             isAnimated : (imageStore.source[drwId].length > 1),
  6172.             frameIndex : 0,
  6173.             frameCount : imageStore.source[drwId].length
  6174.         },
  6175.         inventory : startingInventory,
  6176.         name : name
  6177.     };
  6178.     return i;
  6179. }
  6180.  
  6181. function parseItem(lines, i) {
  6182.     var id = getId(lines[i]);
  6183.     var drwId = null;
  6184.     var name = null;
  6185.  
  6186.     i++;
  6187.  
  6188.     if (getType(lines[i]) === "DRW") { //load existing drawing
  6189.         drwId = getId(lines[i]);
  6190.         i++;
  6191.     }
  6192.     else {
  6193.         // store item source
  6194.         drwId = "ITM_" + id; // these prefixes are maybe a terrible way to differentiate drawing tyepes :/
  6195.         i = parseDrawingCore( lines, i, drwId );
  6196.     }
  6197.  
  6198.     //other properties
  6199.     var colorIndex = 2; //default palette color index is 2
  6200.     var dialogId = null;
  6201.     while (i < lines.length && lines[i].length > 0) { //look for empty line
  6202.         if (getType(lines[i]) === "COL") {
  6203.             /* COLOR OFFSET INDEX */
  6204.             colorIndex = parseInt( getArg( lines[i], 1 ) );
  6205.         }
  6206.         // else if (getType(lines[i]) === "POS") {
  6207.         //  /* STARTING POSITION */
  6208.         //  var posArgs = lines[i].split(" ");
  6209.         //  var roomId = posArgs[1];
  6210.         //  var coordArgs = posArgs[2].split(",");
  6211.         //  spriteStartLocations[id] = {
  6212.         //      room : roomId,
  6213.         //      x : parseInt(coordArgs[0]),
  6214.         //      y : parseInt(coordArgs[1])
  6215.         //  };
  6216.         // }
  6217.         else if(getType(lines[i]) === "DLG") {
  6218.             dialogId = getId(lines[i]);
  6219.         }
  6220.         else if (getType(lines[i]) === "NAME") {
  6221.             /* NAME */
  6222.             name = lines[i].split(/\s(.+)/)[1];
  6223.             names.item.set( name, id );
  6224.         }
  6225.         i++;
  6226.     }
  6227.  
  6228.     //item data
  6229.     item[id] = {
  6230.         drw : drwId, //drawing id
  6231.         col : colorIndex,
  6232.         dlg : dialogId,
  6233.         // room : null, //default location is "offstage"
  6234.         // x : -1,
  6235.         // y : -1,
  6236.         animation : {
  6237.             isAnimated : (imageStore.source[drwId].length > 1),
  6238.             frameIndex : 0,
  6239.             frameCount : imageStore.source[drwId].length
  6240.         },
  6241.         name : name
  6242.     };
  6243.  
  6244.     // console.log("ITM " + id);
  6245.     // console.log(item[id]);
  6246.  
  6247.     return i;
  6248. }
  6249.  
  6250. function parseDrawing(lines, i) {
  6251.     // store drawing source
  6252.     var drwId = getId( lines[i] );
  6253.     return parseDrawingCore( lines, i, drwId );
  6254. }
  6255.  
  6256. function parseDrawingCore(lines, i, drwId) {
  6257.     imageStore.source[drwId] = []; //init list of frames
  6258.     imageStore.source[drwId].push( [] ); //init first frame
  6259.     var frameIndex = 0;
  6260.     var y = 0;
  6261.     while ( y < tilesize ) {
  6262.         var l = lines[i+y];
  6263.         var row = [];
  6264.         for (x = 0; x < tilesize; x++) {
  6265.             row.push( parseInt( l.charAt(x) ) );
  6266.         }
  6267.         imageStore.source[drwId][frameIndex].push( row );
  6268.         y++;
  6269.  
  6270.         if (y === tilesize) {
  6271.             i = i + y;
  6272.             if ( lines[i] != undefined && lines[i].charAt(0) === ">" ) {
  6273.                 // start next frame!
  6274.                 imageStore.source[drwId].push( [] );
  6275.                 frameIndex++;
  6276.                 //start the count over again for the next frame
  6277.                 i++;
  6278.                 y = 0;
  6279.             }
  6280.         }
  6281.     }
  6282.  
  6283.     //console.log(imageStore.source[drwId]);
  6284.     return i;
  6285. }
  6286.  
  6287. function renderImages() {
  6288.     console.log(" -- RENDER IMAGES -- ");
  6289.  
  6290.     //init image store
  6291.     for (pal in palette) {
  6292.         imageStore.render[pal] = {
  6293.             "1" : {}, //images with primary color index 1 (usually tiles)
  6294.             "2" : {}  //images with primary color index 2 (usually sprites)
  6295.         };
  6296.     }
  6297.  
  6298.     //render images required by sprites
  6299.     for (s in sprite) {
  6300.         var spr = sprite[s];
  6301.         renderImageForAllPalettes( spr );
  6302.     }
  6303.     //render images required by tiles
  6304.     for (t in tile) {
  6305.         var til = tile[t];
  6306.         renderImageForAllPalettes( til );
  6307.     }
  6308.     //render images required by tiles
  6309.     for (i in item) {
  6310.         var itm = item[i];
  6311.         renderImageForAllPalettes( itm );
  6312.     }
  6313. }
  6314.  
  6315. function renderImageForAllPalettes(drawing) {
  6316.     console.log("RENDER IMAGE");
  6317.     for (pal in palette) {
  6318.         // console.log(pal);
  6319.  
  6320.         var col = drawing.col;
  6321.         var colStr = "" + col;
  6322.  
  6323.         // slightly hacky initialization of image store for palettes with more than 3 colors ~~~ SECRET FEATURE DO NOT USE :P ~~~
  6324.         if(imageStore.render[pal][colStr] === undefined || imageStore.render[pal][colStr] === null) {
  6325.             console.log("UNDEFINED " + colStr);
  6326.             imageStore.render[pal][colStr] = {};
  6327.         }
  6328.  
  6329.         // console.log(drawing);
  6330.         // console.log(drawing.drw);
  6331.         // console.log(imageStore);
  6332.  
  6333.         var imgSrc = imageStore.source[ drawing.drw ];
  6334.  
  6335.         if ( imgSrc.length <= 1 ) {
  6336.             // non-animated drawing
  6337.             var frameSrc = imgSrc[0];
  6338.             console.log(drawing);
  6339.             console.log(imageStore);
  6340.             imageStore.render[pal][colStr][drawing.drw] = imageDataFromImageSource( frameSrc, pal, col );
  6341.         }
  6342.         else {
  6343.             // animated drawing
  6344.             var frameCount = 0;
  6345.             for (f in imgSrc) {
  6346.                 var frameSrc = imgSrc[f];
  6347.                 var frameId = drawing.drw + "_" + frameCount;
  6348.                 imageStore.render[pal][colStr][frameId] = imageDataFromImageSource( frameSrc, pal, col );
  6349.                 frameCount++;
  6350.             }
  6351.         }
  6352.     }
  6353. }
  6354.  
  6355. function imageDataFromImageSource(imageSource, pal, col) {
  6356.     //console.log(imageSource);
  6357.  
  6358.     var img = ctx.createImageData(tilesize*scale,tilesize*scale);
  6359.     for (var y = 0; y < tilesize; y++) {
  6360.         for (var x = 0; x < tilesize; x++) {
  6361.             var px = imageSource[y][x];
  6362.             for (var sy = 0; sy < scale; sy++) {
  6363.                 for (var sx = 0; sx < scale; sx++) {
  6364.                     var pxl = (((y * scale) + sy) * tilesize * scale * 4) + (((x*scale) + sx) * 4);
  6365.                     if ( px === 1 && getPal(pal).length > col ) {
  6366.                         img.data[pxl + 0] = getPal(pal)[col][0]; //ugly
  6367.                         img.data[pxl + 1] = getPal(pal)[col][1];
  6368.                         img.data[pxl + 2] = getPal(pal)[col][2];
  6369.                         img.data[pxl + 3] = 255;
  6370.                     }
  6371.                     else { //ch === 0
  6372.                         img.data[pxl + 0] = getPal(pal)[0][0];
  6373.                         img.data[pxl + 1] = getPal(pal)[0][1];
  6374.                         img.data[pxl + 2] = getPal(pal)[0][2];
  6375.                         img.data[pxl + 3] = 255;
  6376.                     }
  6377.                 }
  6378.             }
  6379.         }
  6380.     }
  6381.     return img;
  6382. }
  6383.  
  6384. function parseDialog(lines, i) {
  6385.     var id = getId(lines[i]);
  6386.     i++;
  6387.  
  6388.     // TODO : use this for titles & endings too
  6389.     var results = scriptInterpreter.ReadDialogScript(lines,i);
  6390.     dialog[id] = results.script;
  6391.     i = results.index;
  6392.  
  6393.     return i;
  6394. }
  6395.  
  6396. function parseEnding(lines, i) {
  6397.     var id = getId(lines[i]);
  6398.     i++;
  6399.     var text = lines[i];
  6400.     i++;
  6401.     ending[id] = text;
  6402.     return i;
  6403. }
  6404.  
  6405. function parseVariable(lines, i) {
  6406.     var id = getId(lines[i]);
  6407.     i++;
  6408.     var value = lines[i];
  6409.     i++;
  6410.     variable[id] = value;
  6411.     return i;
  6412. }
  6413.  
  6414. function parseFlag(lines, i) {
  6415.     var id = getId(lines[i]);
  6416.     var valStr = lines[i].split(" ")[2];
  6417.     flags[id] = parseInt( valStr );
  6418.     i++;
  6419.     return i;
  6420. }
  6421.  
  6422. function drawTile(img,x,y,context) {
  6423.     if (!context) { //optional pass in context; otherwise, use default
  6424.         context = ctx;
  6425.     }
  6426.     context.putImageData(img,x*tilesize*scale,y*tilesize*scale);
  6427. }
  6428.  
  6429. function drawSprite(img,x,y,context) { //this may differ later (or not haha)
  6430.     drawTile(img,x,y,context);
  6431. }
  6432.  
  6433. function drawItem(img,x,y,context) {
  6434.     drawTile(img,x,y,context); //TODO these methods are dumb and repetitive
  6435. }
  6436.  
  6437. function drawRoom(room,context) {
  6438.     //draw tiles
  6439.     for (i in room.tilemap) {
  6440.         for (j in room.tilemap[i]) {
  6441.             var id = room.tilemap[i][j];
  6442.             if (id != "0") {
  6443.                 //console.log(id);
  6444.                 if (tile[id] == null) { // hack-around to avoid corrupting files (not a solution though!)
  6445.                     id = "0";
  6446.                     room.tilemap[i][j] = id;
  6447.                 }
  6448.                 else {
  6449.                     // console.log(id);
  6450.                     drawTile( getTileImage(tile[id],getRoomPal(room.id)), j, i, context );
  6451.                 }
  6452.             }
  6453.         }
  6454.     }
  6455.     //draw items
  6456.     for (var i = 0; i < room.items.length; i++) {
  6457.         var itm = room.items[i];
  6458.         drawItem( getItemImage(item[itm.id],getRoomPal(room.id)), itm.x, itm.y, context );
  6459.     }
  6460.     //draw sprites
  6461.     for (id in sprite) {
  6462.         var spr = sprite[id];
  6463.         if (spr.room === room.id) {
  6464.             drawSprite( getSpriteImage(spr,getRoomPal(room.id)), spr.x, spr.y, context );
  6465.         }
  6466.     }
  6467. }
  6468.  
  6469. function getTileImage(t,palId,frameIndex) {
  6470.     if( frameIndex === undefined ) frameIndex = null; // no default parameter support on iOS
  6471.  
  6472.     var drwId = t.drw;
  6473.  
  6474.     if (!palId) palId = curPal();
  6475.  
  6476.     if ( t.animation.isAnimated ) {
  6477.         if (frameIndex != null) { // use optional provided frame index
  6478.             // console.log("GET TILE " + frameIndex);
  6479.             drwId += "_" + frameIndex;
  6480.         }
  6481.         else { // or the one bundled with the tile
  6482.             drwId += "_" + t.animation.frameIndex;
  6483.         }
  6484.     }
  6485.     return imageStore.render[ palId ][ t.col ][ drwId ];
  6486. }
  6487.  
  6488. function getSpriteImage(s,palId,frameIndex) {
  6489.     if( frameIndex === undefined ) frameIndex = null; // no default parameter support on iOS
  6490.  
  6491.     var drwId = s.drw;
  6492.  
  6493.     if (!palId) palId = curPal();
  6494.  
  6495.     if ( s.animation.isAnimated ) {
  6496.         if (frameIndex != null) {
  6497.             drwId += "_" + frameIndex;
  6498.         }
  6499.         else {
  6500.             drwId += "_" + s.animation.frameIndex;
  6501.         }
  6502.     }
  6503.  
  6504.     return imageStore.render[ palId ][ s.col ][ drwId ];
  6505. }
  6506.  
  6507. function getItemImage(itm,palId,frameIndex) { //aren't these all the same????
  6508.     if( frameIndex === undefined ) frameIndex = null; // no default parameter support on iOS
  6509.  
  6510.     var drwId = itm.drw;
  6511.     // console.log(drwId);
  6512.  
  6513.     if (!palId) palId = curPal();
  6514.  
  6515.     if ( itm.animation.isAnimated ) {
  6516.         if (frameIndex != null) {
  6517.             drwId += "_" + frameIndex;
  6518.         }
  6519.         else {
  6520.             drwId += "_" + itm.animation.frameIndex;
  6521.         }
  6522.     }
  6523.  
  6524.     // console.log(imageStore.render[ palId ][ itm.col ]);
  6525.     // console.log(imageStore.render[ palId ][ itm.col ][ drwId ]);
  6526.     return imageStore.render[ palId ][ itm.col ][ drwId ];
  6527. }
  6528.  
  6529. function curPal() {
  6530.     return getRoomPal(curRoom);
  6531. }
  6532.  
  6533. function getRoomPal(roomId) {
  6534.     if (room[roomId].pal != null) {
  6535.         //a specific palette was chosen
  6536.         return room[roomId].pal;
  6537.     }
  6538.     else {
  6539.         if (roomId in palette) {
  6540.             //there is a palette matching the name of the room
  6541.             return roomId;
  6542.         }
  6543.         else {
  6544.             //use the default palette
  6545.             return "0";
  6546.         }
  6547.     }
  6548.     return "0";
  6549. }
  6550.  
  6551. var isDialogMode = false;
  6552. var isNarrating = false;
  6553. var isEnding = false;
  6554. var dialogModule = new Dialog();
  6555. var dialogRenderer = dialogModule.CreateRenderer();
  6556. var dialogBuffer = dialogModule.CreateBuffer();
  6557.  
  6558. function onExitDialog() {
  6559.     // var breakShit = null;
  6560.     // breakShit();
  6561.     console.log("EXIT DIALOG");
  6562.     isDialogMode = false;
  6563.     if (isNarrating) isNarrating = false;
  6564.     if (isDialogPreview) {
  6565.         isDialogPreview = false;
  6566.         if (onDialogPreviewEnd != null)
  6567.             onDialogPreviewEnd();
  6568.     }
  6569. }
  6570.  
  6571. /*
  6572. TODO
  6573. - titles and endings should also take advantage of the script pre-compilation if possible??
  6574. - could there be a namespace collision?
  6575. - what about dialog NAMEs vs IDs?
  6576. - what about a special script block separate from DLG?
  6577. */
  6578. function startNarrating(dialogStr,end) {
  6579.     console.log("NARRATE " + dialogStr);
  6580.  
  6581.     if(end === undefined) end = false;
  6582.  
  6583.     isNarrating = true;
  6584.     isEnding = end;
  6585.     startDialog(dialogStr);
  6586. }
  6587.  
  6588. function startItemDialog(itemId) {
  6589.     var dialogId = item[itemId].dlg;
  6590.     // console.log("START ITEM DIALOG " + dialogId);
  6591.     if(dialog[dialogId]){
  6592.         var dialogStr = dialog[dialogId];
  6593.         startDialog(dialogStr,dialogId);
  6594.     }
  6595. }
  6596.  
  6597. function startSpriteDialog(spriteId) {
  6598.     var spr = sprite[spriteId];
  6599.     var dialogId = spr.dlg ? spr.dlg : spriteId;
  6600.     // console.log("START SPRITE DIALOG " + dialogId);
  6601.     if(dialog[dialogId]){
  6602.         var dialogStr = dialog[dialogId];
  6603.         startDialog(dialogStr,dialogId);
  6604.     }
  6605. }
  6606.  
  6607. function startDialog(dialogStr,scriptId) {
  6608.     if(dialogStr.length <= 0) {
  6609.         console.log("ON EXIT DIALOG -- startDialog 1");
  6610.         onExitDialog();
  6611.         return;
  6612.     }
  6613.  
  6614.     isDialogMode = true;
  6615.  
  6616.     dialogRenderer.Reset();
  6617.     dialogRenderer.SetCentered( isNarrating /*centered*/ );
  6618.     dialogBuffer.Reset();
  6619.     scriptInterpreter.SetDialogBuffer( dialogBuffer );
  6620.  
  6621.     var onScriptEnd = function() {
  6622.         if(!dialogBuffer.IsActive()){
  6623.             console.log("ON EXIT DIALOG -- startDialog 2");
  6624.             onExitDialog();
  6625.         }
  6626.     };
  6627.  
  6628.     if(scriptId === undefined) {
  6629.         scriptInterpreter.Interpret( dialogStr, onScriptEnd );     
  6630.     }
  6631.     else {
  6632.         if( !scriptInterpreter.HasScript(scriptId) )
  6633.             scriptInterpreter.Compile( scriptId, dialogStr );
  6634.         scriptInterpreter.Run( scriptId, onScriptEnd );
  6635.     }
  6636.  
  6637. }
  6638.  
  6639. var isDialogPreview = false;
  6640. function startPreviewDialog(script, onScriptEnd) {
  6641.     isNarrating = true;
  6642.  
  6643.     isDialogMode = true;
  6644.  
  6645.     isDialogPreview = true;
  6646.  
  6647.     dialogRenderer.Reset();
  6648.     dialogRenderer.SetCentered( true );
  6649.     dialogBuffer.Reset();
  6650.     scriptInterpreter.SetDialogBuffer( dialogBuffer );
  6651.  
  6652.     onDialogPreviewEnd = onScriptEnd;
  6653.  
  6654.     scriptInterpreter.Eval( script, null );
  6655. }
  6656.  
  6657. /* NEW SCRIPT STUFF */
  6658. var scriptModule = new Script();
  6659. var scriptInterpreter = scriptModule.CreateInterpreter();
  6660. var scriptUtils = scriptModule.CreateUtils(); // TODO: move to editor.js?
  6661. // scriptInterpreter.SetDialogBuffer( dialogBuffer );
  6662. </script>
  6663.  
  6664. </head>
  6665.  
  6666.  
  6667. <!-- DOCUMENT BODY -->
  6668. <body onload='startExportedGame()'>
  6669.     <!-- GAME CANVAS -->
  6670.     <canvas id='game'></canvas>
  6671. </body>
  6672.  
  6673.  
  6674. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement