1
2 /*
3
4 This is the compressor which is used to reduce the size of the game 'build'
5 output considerably. The tool compresses the game build, and a minified copy
6 of everything here *except* hootCompress() is in examplegame.html so that the
7 game can be decompressed before it is played.
8
9 NOTE: examplegame.html copy minified with UglifyJS (at jscompress.com)
10
11
12
13 The dictionary compression approach is very fast and quite effective.
14 Results of a small sample script are:
15
16 Game source: 2169
17 Game: 2606 (-20% vs src)
18 Compressed: 1620 (25% vs src, 38% vs 'orig' build)
19 Decompressed same?: true
20
21 */
22
23
24 // minification starts here...
25
26
27 // The Compression Dictionary - see comments below about its creation
28 // -----------------------------------------------------------------------------
29 var dict = ["\"],[\"break\",\"__\"],[\"string\",\"", "[[\"script\",[\"func\",[\"name\",\"", "\"],[\"print\",[\"string\",\"", "\"]]],[\"func\",[\"name\",\"", "\"],[\"break\",\"__\"]", "[\"func\",[\"name\",\"", "\"],[\"string\",\"", " \"],[\"link\",\"", ",[\"string\",\"", "\"],[\"link\",\"", "\",[\"name\",\"", "[[\"script\"", " of the ", " through", "start", " of the", " of th", " that ", " with ", " your ", ". The ", "n the ", " and ", " are ", " for ", " the ", " The ", " with", " you ", " You ", ". The", "\"],[\"", "]],[\"", "h you", "ight ", "n the", "s the", "s you", " and", " are", " for", " in ", " is ", " of ", " the", " The", " to ", " whe", " you", " You", ". Th", "\"]]]", "],[\"", "and ", "e th", "hat ", "ight", "ing ", "ion ", "ith ", "k\",\"", "me\",", "n th", "our ", "r po", "s of", "s th", "t th", "ter ", "The ", "You ", " a ", " A ", " an", " ar", " as", " be", " bo", " ca", " co", " di", " do", " dr", " fo", " fr", " ha", " he", " in", " is", " it", " li", " ma", " mi", " no", " of", " on", " pa", " po", " re", " ro", " se", " st", " th", " Th", " to", " wa", " wh", " wi", " wo", "'s ", ",[\"", ". ", ". T", "\",\"", "\"]]", "]]]", "ain", "al ", "all", "and", "ant", "ard", "are", "as ", "at ", "ate", "ce ", "ch ", "ck ", "cke", "d b", "d t", "d. ", "e a", "e b", "e c", "e f", "e i", "e o", "e p", "e r", "e s", "e t", "e w", "e. ", "ead", "ear", "eat", "ed ", "en ", "ent", "er ", "ere", "ers", "es ", "est", "f t", "for", "fun", "ght", "hat", "he ", "her", "hin", "his", "igh", "ill", "in ", "ine", "ing", "int", "ion", "is ", "ite", "ith", "ive", "ke ", "le ", "ll ", "ly ", "n t", "nd ", "ne ", "ng ", "nt ", "o t", "of ", "on ", "one", "or ", "ou ", "oun", "our", "ow ", "per", "pla", "r t", "r. ", "rd ", "re ", "rea", "res", "s a", "s o", "s t", "s. ", "se ", "st ", "t a", "t l", "t o", "t t", "t. ", "te ", "ter", "th ", "the", "The", "thi", "to ", "ts ", "tur", "und", "ur ", "ure", "use", "ut ", "ve ", "ver", "wit", "wor", "y a", "You", "you", "run", "\"]", "\\", "\""];
30 // -----------------------------------------------------------------------------
31
32 // currently this allows for 300-something dictionary entries - the above list is 235
33 var hootCompressionCode = [];
34 for(var i=164; i<167; i++){ // ¤¥¦
35 for(var j=35; j<127; j++){
36 if(j==92){ continue; } // the backslash will cause string trouble!
37 hootCompressionCode.push(String.fromCharCode(i,j));
38 }
39 }
40
41 function rot13(script){ // http://stackoverflow.com/a/5353260/695615
42 return script.replace(/[a-zA-Z]/g, function(c) {
43 return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
44 });
45 }
46
47
48
49
50 // =============================================================================
51 // The decompressor will be minified and included with the examplegame.html
52 // page, along with a minified copy of the dictionary, code table, and rot13.
53 // =============================================================================
54
55 function hootDecompress(script){
56 script = rot13(script);
57 for(var i=dict.length-1; i>=0; i--){ // see note below about reverse order
58 // we can't use replace() because it only replaces globaly with
59 // regular expressions - and we definitely can't use our dictionary
60 // entries as regular expressions (and if they were modified so that
61 // we could, they would not be reversible back to the original strings!)
62 script = script.split(hootCompressionCode[i]).join(dict[i]);
63 }
64 return script;
65 }
66
67
68 // ...and ends here
69
70
71 // =============================================================================
72 // The compressor is called directly from here by hoot-builder.js when building
73 // the game output.
74 // =============================================================================
75 function hootCompress(script){
76 for(d in dict){
77 // see note above about why we can't just use replace
78 script = script.split(dict[d]).join(hootCompressionCode[d]);
79 }
80 return rot13(script);
81 }
82
83
84
85
86 /*
87
88 A note about the decompression running through the dictionary on reverse order
89 when deompressing:
90
91 It's completely possible for a replacement to match the results of a previous
92 replacement, totally corrupting the output. For example, given these two
93 replacements:
94
95 replace 'oo' with '$ee'
96 replace 'ee ba' with '$xx'
97
98 Now imagine the string "foo bar fee bar" being replaced with these two replacements.
99 It would be corrupted if we were to undo the replacements in the same order, but
100 completely fine if we undid the replacements in the reverse order.
101
102
103
104 A note about the dictionary.
105
106 The common strings were created using hoot-create-dictionary.html
107 to extract commonly-used strings from some representative text. Namely:
108
109 Some sample Hootscript games produced these common strings:
110 Settings:
111 var max_likely_string_len = 100;
112 var min_string_len = 3;
113 var min_frequency = 5;
114 --------------------------------------------------------------------------------
115 ",[\"", "\",\"", "],[\"", "ing", " you", "tri", ",[\"string\",\"", "the", "ou ", " the", "he ", " of", " a ", "k\",\"", " to", " of ", "\"],[\"string\",\"", "nd ", " the ", " your ", "to ", "and", " to ", " an", "re ", "e t", "rea", "]]]", " you ", "int", "and ", "me\",", "You", " and ", " po", "\",[\"name\",\"", "\"],[\"link\",\"", "\"]]", "fun", "ed ", "You ", "\"],[\"print\",[\"string\",\"", "\"]]]", ",[\"func\",[\"name\",\"", "e a", "er ", " be", "ing ", "]],[\"", ". ", "y a", "ve ", "\"]", "\"],[\"string\",\"", "ith", "t a", "e w", "\"]]],[\"func\",[\"name\",\"", "e th", " ar", " li", " \"],[\"link\",\"", "her", "\"],[\"", "ight", "ter", "at ", "e o", "on ", " co", "\"],[\"break\",\"__\"]", "st ", "cke", "th ", "for", "ead", " are", " se", "ll ", "h you", "s t", "r t", "t o", "f t", "ate", "ere", "one", " through", "\"],[\"break\",\"__\"],[\"string\",\"", "s you", "r po", "is ", "ight ", "pla", "t l", ", you", "ain", "e s", "or ", " are ", " whe", " wo", " with ", " that ", " You ", " pa", "ly "
116 --------------------------------------------------------------------------------
117
118
119 A massaged copy of the Return to Zork script produced these common strings:
120 Settings:
121 var max_likely_string_len = 10;
122 var min_string_len = 3;
123 var min_frequency = 30;
124 --------------------------------------------------------------------------------
125 "he ", " th", "the", " the", " the ", "ing", " of", " ", "of ", " of ", "ng ", "ed ", "ing ", " Th", " to", "nd ", "The", " The", "to ", "er ", " in", "re ", "The ", " The ", "ou ", " to ", " an", "is ", "at ", " a ", "and", "in ", "es ", " ", ". T", "st ", " you", "ll ", "th ", " You", "s. ", "and ", " wi", "on ", "en ", "e t", " be", "ter", " in ", " and", " and ", ". ", "e. ", "s t", "n t", " is", " fo", ". Th", "or ", " is ", " You ", " re", " ma", "d t", "ts ", " ha", "ck ", "her", "e o", "hat", "e a", "le ", "for", " on", "ion", "all", "f t", " of th", ". The", "ve ", " st", " of the", "n th", " wa", " co", "as ", "ow ", "se ", " of the ", "t t", "ith", "ent", "ut ", "ly ", "ver", " for", "ere", "hat ", "e i", "ers", "n the", " you ", "our", "ill", "ate", ". The ", " ca", "s o", "tur", "ce ", "s a", "e s", "ear", "wit", " with", "ith ", "e b", "n the ", "d. ", "res", "und", "e w", " wh", "oun", "t a", "ite", "e r", "rd ", " with ", " no", "e f", "t. ", "ard", "s th", "eat", "are", "al ", "ch ", " bo", " A ", "ine", "use", " ", "ur ", "his", " fr", " do", "our ", "te ", "igh", "ive", "hin", "wor", "est", "e p", "nt ", "d b", "ght", " it", " ar", "e th", "ne ", "r. ", "ure", " as", " di", " mi", "s the", "t th", "thi", "e c", "ead", "ke ", "per", "'s ", " , ", "o t", "s of", "t o", "ter ", "ant", " dr", " he", "ight", "ion ", " for ", " ro", " Ca", "ound", "ock", "are ", "ar ", "rea", " Mo", " Tr", " In", "ope", "om ", "e of", "an ", "der", "ood", "out", "ste", "s the ", "tha", "ave", "d th", "rin", " Sh", "ore", "ome", "s of ", "to t", "e d", "eve", "rou", "r t", "rs ", "ry ", "han", " pr", " pl", " so", " mo", "ous", ...
126 --------------------------------------------------------------------------------
127
128 */
129