forked from zp5454/Clasic-Cooke-Clicker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
13357 lines (12063 loc) · 704 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
All this code is copyright Orteil, 2013-2019.
-with some help, advice and fixes by Nicholas Laux, Debugbro, Opti, and lots of people on reddit, Discord, and the DashNet forums
-also includes a bunch of snippets found on stackoverflow.com and others
Hello, and welcome to the joyous mess that is main.js. Code contained herein is not guaranteed to be good, consistent, or sane. Most of this is years old at this point and harkens back to simpler, cruder times. Have a nice trip.
Spoilers ahead.
http://orteil.dashnet.org
*/
var VERSION=2.019;
var BETA=1;
/*=====================================================================================
MISC HELPER FUNCTIONS
=======================================================================================*/
function l(what) {return document.getElementById(what);}
function choose(arr) {return arr[Math.floor(Math.random()*arr.length)];}
function escapeRegExp(str){return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");}
function replaceAll(find,replace,str){return str.replace(new RegExp(escapeRegExp(find),'g'),replace);}
//disable sounds coming from soundjay.com (sorry)
var realAudio=Audio;//backup real audio
Audio=function(src){
if (src && src.indexOf('soundjay')>-1) {Game.Popup('Sorry, no sounds hotlinked from soundjay.com.');this.play=function(){};}
else return new realAudio(src);
};
if(!Array.prototype.indexOf) {
Array.prototype.indexOf = function(needle) {
for(var i = 0; i < this.length; i++) {
if(this[i] === needle) {return i;}
}
return -1;
};
}
function randomFloor(x) {if ((x%1)<Math.random()) return Math.floor(x); else return Math.ceil(x);}
function shuffle(array)
{
var counter = array.length, temp, index;
// While there are elements in the array
while (counter--)
{
// Pick a random index
index = (Math.random() * counter) | 0;
// And swap the last element with it
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
var sinArray=[];
for (var i=0;i<360;i++)
{
//let's make a lookup table
sinArray[i]=Math.sin(i/360*Math.PI*2);
}
function quickSin(x)
{
//oh man this isn't all that fast actually
//why do I do this. why
var sign=x<0?-1:1;
return sinArray[Math.round(
(Math.abs(x)*360/Math.PI/2)%360
)]*sign;
}
/*function ajax(url,callback){
var ajaxRequest;
try{ajaxRequest = new XMLHttpRequest();} catch (e){try{ajaxRequest=new ActiveXObject('Msxml2.XMLHTTP');} catch (e) {try{ajaxRequest=new ActiveXObject('Microsoft.XMLHTTP');} catch (e){alert("Something broke!");return false;}}}
if (callback){ajaxRequest.onreadystatechange=function(){if(ajaxRequest.readyState==4){callback(ajaxRequest.responseText);}}}
ajaxRequest.open('GET',url+'&nocache='+(new Date().getTime()),true);ajaxRequest.send(null);
}*/
var ajax=function(url,callback)
{
var httpRequest=new XMLHttpRequest();
if (!httpRequest){return false;}
httpRequest.onreadystatechange=function()
{
try{
if (httpRequest.readyState===XMLHttpRequest.DONE && httpRequest.status===200)
{
callback(httpRequest.responseText);
}
}catch(e){}
}
//httpRequest.onerror=function(e){console.log('ERROR',e);}
if (url.indexOf('?')==-1) url+='?'; else url+='&';
url+='nocache='+Date.now();
httpRequest.open('GET',url);
httpRequest.setRequestHeader('Content-Type','text/plain');
httpRequest.overrideMimeType('text/plain');
httpRequest.send();
return true;
}
//Beautify and number-formatting adapted from the Frozen Cookies add-on (http://cookieclicker.wikia.com/wiki/Frozen_Cookies_%28JavaScript_Add-on%29)
function formatEveryThirdPower(notations)
{
return function (value)
{
var base = 0,
notationValue = '';
if (!isFinite(value)) return 'Infinity';
if (value >= 1000000)
{
value /= 1000;
while(Math.round(value) >= 1000)
{
value /= 1000;
base++;
}
if (base >= notations.length) {return 'Infinity';} else {notationValue = notations[base];}
}
return ( Math.round(value * 1000) / 1000 ) + notationValue;
};
}
function rawFormatter(value) {return Math.round(value * 1000) / 1000;}
var formatLong=[' thousand',' million',' billion',' trillion',' quadrillion',' quintillion',' sextillion',' septillion',' octillion',' nonillion'];
var prefixes=['','un','duo','tre','quattuor','quin','sex','septen','octo','novem'];
var suffixes=['decillion','vigintillion','trigintillion','quadragintillion','quinquagintillion','sexagintillion','septuagintillion','octogintillion','nonagintillion'];
for (var i in suffixes)
{
for (var ii in prefixes)
{
formatLong.push(' '+prefixes[ii]+suffixes[i]);
}
}
var formatShort=['k','M','B','T','Qa','Qi','Sx','Sp','Oc','No'];
var prefixes=['','Un','Do','Tr','Qa','Qi','Sx','Sp','Oc','No'];
var suffixes=['D','V','T','Qa','Qi','Sx','Sp','O','N'];
for (var i in suffixes)
{
for (var ii in prefixes)
{
formatShort.push(' '+prefixes[ii]+suffixes[i]);
}
}
formatShort[10]='Dc';
var numberFormatters =
[
formatEveryThirdPower(formatShort),
formatEveryThirdPower(formatLong),
rawFormatter
];
function Beautify(value,floats)
{
var negative=(value<0);
var decimal='';
var fixed=value.toFixed(floats);
if (Math.abs(value)<1000 && floats>0 && Math.floor(fixed)!=fixed) decimal='.'+(fixed.toString()).split('.')[1];
value=Math.floor(Math.abs(value));
if (floats>0 && fixed==value+1) value++;
var formatter=numberFormatters[Game.prefs.format?2:1];
var output=formatter(value).toString().replace(/\B(?=(\d{3})+(?!\d))/g,',');
if (output=='0') negative=false;
return negative?'-'+output:output+decimal;
}
function shortenNumber(value)
{
//if no scientific notation, return as is, else :
//keep only the 5 first digits (plus dot), round the rest
//may or may not work properly
if (value >= 1000000 && isFinite(value))
{
var num=value.toString();
var ind=num.indexOf('e+');
if (ind==-1) return value;
var str='';
for (var i=0;i<ind;i++)
{
str+=(i<6?num[i]:'0');
}
str+='e+';
str+=num.split('e+')[1];
return parseFloat(str);
}
return value;
}
var beautifyInTextFilter=/(([\d]+[,]*)+)/g;//new regex
var a=/\d\d?\d?(?:,\d\d\d)*/g;//old regex
function BeautifyInTextFunction(str){return Beautify(parseInt(str.replace(/,/g,''),10));};
function BeautifyInText(str) {return str.replace(beautifyInTextFilter,BeautifyInTextFunction);}//reformat every number inside a string
function BeautifyAll()//run through upgrades and achievements to reformat the numbers
{
var func=function(what){what.desc=BeautifyInText(what.baseDesc);}
Game.UpgradesById.forEach(func);
Game.AchievementsById.forEach(func);
}
//these are faulty, investigate later
//function utf8_to_b64(str){return btoa(str);}
//function b64_to_utf8(str){return atob(str);}
function utf8_to_b64( str ) {
try{return Base64.encode(unescape(encodeURIComponent( str )));}
catch(err)
{return '';}
}
function b64_to_utf8( str ) {
try{return decodeURIComponent(escape(Base64.decode( str )));}
catch(err)
{return '';}
}
function CompressBin(arr)//compress a sequence like [0,1,1,0,1,0]... into a number like 54.
{
var str='';
var arr2=arr.slice(0);
arr2.unshift(1);
arr2.push(1);
arr2.reverse();
for (var i in arr2)
{
str+=arr2[i];
}
str=parseInt(str,2);
return str;
}
function UncompressBin(num)//uncompress a number like 54 to a sequence like [0,1,1,0,1,0].
{
var arr=num.toString(2);
arr=arr.split('');
arr.reverse();
arr.shift();
arr.pop();
return arr;
}
function CompressLargeBin(arr)//we have to compress in smaller chunks to avoid getting into scientific notation
{
var arr2=arr.slice(0);
var thisBit=[];
var bits=[];
for (var i in arr2)
{
thisBit.push(arr2[i]);
if (thisBit.length>=50)
{
bits.push(CompressBin(thisBit));
thisBit=[];
}
}
if (thisBit.length>0) bits.push(CompressBin(thisBit));
arr2=bits.join(';');
return arr2;
}
function UncompressLargeBin(arr)
{
var arr2=arr.split(';');
var bits=[];
for (var i in arr2)
{
bits.push(UncompressBin(parseInt(arr2[i])));
}
arr2=[];
for (var i in bits)
{
for (var ii in bits[i]) arr2.push(bits[i][ii]);
}
return arr2;
}
function pack(bytes) {
var chars = [];
var len=bytes.length;
for(var i = 0, n = len; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = [];
var len=str.length;
for(var i = 0, n = len; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
//modified from http://www.smashingmagazine.com/2011/10/19/optimizing-long-lists-of-yesno-values-with-javascript/
function pack2(/* string */ values) {
var chunks = values.match(/.{1,14}/g), packed = '';
for (var i=0; i < chunks.length; i++) {
packed += String.fromCharCode(parseInt('1'+chunks[i], 2));
}
return packed;
}
function unpack2(/* string */ packed) {
var values = '';
for (var i=0; i < packed.length; i++) {
values += packed.charCodeAt(i).toString(2).substring(1);
}
return values;
}
function pack3(values){
//too many save corruptions, darn it to heck
return values;
}
//file save function from https://github.com/eligrey/FileSaver.js
var saveAs=saveAs||function(view){"use strict";if(typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var doc=view.document,get_URL=function(){return view.URL||view.webkitURL||view},save_link=doc.createElementNS("http://www.w3.org/1999/xhtml","a"),can_use_save_link="download"in save_link,click=function(node){var event=new MouseEvent("click");node.dispatchEvent(event)},is_safari=/Version\/[\d\.]+.*Safari/.test(navigator.userAgent),webkit_req_fs=view.webkitRequestFileSystem,req_fs=view.requestFileSystem||webkit_req_fs||view.mozRequestFileSystem,throw_outside=function(ex){(view.setImmediate||view.setTimeout)(function(){throw ex},0)},force_saveable_type="application/octet-stream",fs_min_size=0,arbitrary_revoke_timeout=500,revoke=function(file){var revoker=function(){if(typeof file==="string"){get_URL().revokeObjectURL(file)}else{file.remove()}};if(view.chrome){revoker()}else{setTimeout(revoker,arbitrary_revoke_timeout)}},dispatch=function(filesaver,event_types,event){event_types=[].concat(event_types);var i=event_types.length;while(i--){var listener=filesaver["on"+event_types[i]];if(typeof listener==="function"){try{listener.call(filesaver,event||filesaver)}catch(ex){throw_outside(ex)}}}},auto_bom=function(blob){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)){return new Blob(["\ufeff",blob],{type:blob.type})}return blob},FileSaver=function(blob,name,no_auto_bom){if(!no_auto_bom){blob=auto_bom(blob)}var filesaver=this,type=blob.type,blob_changed=false,object_url,target_view,dispatch_all=function(){dispatch(filesaver,"writestart progress write writeend".split(" "))},fs_error=function(){if(target_view&&is_safari&&typeof FileReader!=="undefined"){var reader=new FileReader;reader.onloadend=function(){var base64Data=reader.result;target_view.location.href="data:attachment/file"+base64Data.slice(base64Data.search(/[,;]/));filesaver.readyState=filesaver.DONE;dispatch_all()};reader.readAsDataURL(blob);filesaver.readyState=filesaver.INIT;return}if(blob_changed||!object_url){object_url=get_URL().createObjectURL(blob)}if(target_view){target_view.location.href=object_url}else{var new_tab=view.open(object_url,"_blank");if(new_tab==undefined&&is_safari){view.location.href=object_url}}filesaver.readyState=filesaver.DONE;dispatch_all();revoke(object_url)},abortable=function(func){return function(){if(filesaver.readyState!==filesaver.DONE){return func.apply(this,arguments)}}},create_if_not_found={create:true,exclusive:false},slice;filesaver.readyState=filesaver.INIT;if(!name){name="download"}if(can_use_save_link){object_url=get_URL().createObjectURL(blob);setTimeout(function(){save_link.href=object_url;save_link.download=name;click(save_link);dispatch_all();revoke(object_url);filesaver.readyState=filesaver.DONE});return}if(view.chrome&&type&&type!==force_saveable_type){slice=blob.slice||blob.webkitSlice;blob=slice.call(blob,0,blob.size,force_saveable_type);blob_changed=true}if(webkit_req_fs&&name!=="download"){name+=".download"}if(type===force_saveable_type||webkit_req_fs){target_view=view}if(!req_fs){fs_error();return}fs_min_size+=blob.size;req_fs(view.TEMPORARY,fs_min_size,abortable(function(fs){fs.root.getDirectory("saved",create_if_not_found,abortable(function(dir){var save=function(){dir.getFile(name,create_if_not_found,abortable(function(file){file.createWriter(abortable(function(writer){writer.onwriteend=function(event){target_view.location.href=file.toURL();filesaver.readyState=filesaver.DONE;dispatch(filesaver,"writeend",event);revoke(file)};writer.onerror=function(){var error=writer.error;if(error.code!==error.ABORT_ERR){fs_error()}};"writestart progress write abort".split(" ").forEach(function(event){writer["on"+event]=filesaver["on"+event]});writer.write(blob);filesaver.abort=function(){writer.abort();filesaver.readyState=filesaver.DONE};filesaver.readyState=filesaver.WRITING}),fs_error)}),fs_error)};dir.getFile(name,{create:false},abortable(function(file){file.remove();save()}),abortable(function(ex){if(ex.code===ex.NOT_FOUND_ERR){save()}else{fs_error()}}))}),fs_error)}),fs_error)},FS_proto=FileSaver.prototype,saveAs=function(blob,name,no_auto_bom){return new FileSaver(blob,name,no_auto_bom)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(blob,name,no_auto_bom){if(!no_auto_bom){blob=auto_bom(blob)}return navigator.msSaveOrOpenBlob(blob,name||"download")}}FS_proto.abort=function(){var filesaver=this;filesaver.readyState=filesaver.DONE;dispatch(filesaver,"abort")};FS_proto.readyState=FS_proto.INIT=0;FS_proto.WRITING=1;FS_proto.DONE=2;FS_proto.error=FS_proto.onwritestart=FS_proto.onprogress=FS_proto.onwrite=FS_proto.onabort=FS_proto.onerror=FS_proto.onwriteend=null;return saveAs}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!=null){define([],function(){return saveAs})}
//seeded random function, courtesy of http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html
(function(a,b,c,d,e,f){function k(a){var b,c=a.length,e=this,f=0,g=e.i=e.j=0,h=e.S=[];for(c||(a=[c++]);d>f;)h[f]=f++;for(f=0;d>f;f++)h[f]=h[g=j&g+a[f%c]+(b=h[f])],h[g]=b;(e.g=function(a){for(var b,c=0,f=e.i,g=e.j,h=e.S;a--;)b=h[f=j&f+1],c=c*d+h[j&(h[f]=h[g=j&g+b])+(h[g]=b)];return e.i=f,e.j=g,c})(d)}function l(a,b){var e,c=[],d=(typeof a)[0];if(b&&"o"==d)for(e in a)try{c.push(l(a[e],b-1))}catch(f){}return c.length?c:"s"==d?a:a+"\0"}function m(a,b){for(var d,c=a+"",e=0;c.length>e;)b[j&e]=j&(d^=19*b[j&e])+c.charCodeAt(e++);return o(b)}function n(c){try{return a.crypto.getRandomValues(c=new Uint8Array(d)),o(c)}catch(e){return[+new Date,a,a.navigator.plugins,a.screen,o(b)]}}function o(a){return String.fromCharCode.apply(0,a)}var g=c.pow(d,e),h=c.pow(2,f),i=2*h,j=d-1;c.seedrandom=function(a,f){var j=[],p=m(l(f?[a,o(b)]:0 in arguments?a:n(),3),j),q=new k(j);return m(o(q.S),b),c.random=function(){for(var a=q.g(e),b=g,c=0;h>a;)a=(a+c)*d,b*=d,c=q.g(1);for(;a>=i;)a/=2,b/=2,c>>>=1;return(a+c)/b},p},m(c.random(),b)})(this,[],Math,256,6,52);
function bind(scope,fn)
{
//use : bind(this,function(){this.x++;}) - returns a function where "this" refers to the scoped this
return function() {fn.apply(scope,arguments);};
}
var grabProps=function(arr,prop)
{
if (!arr) return [];
arr2=[];
for (var i=0;i<arr.length;i++)
{
arr2.push(arr[i][prop]);
}
return arr2;
}
CanvasRenderingContext2D.prototype.fillPattern=function(img,X,Y,W,H,iW,iH,offX,offY)
{
//for when built-in patterns aren't enough
if (img.alt!='blank')
{
var offX=offX||0;
var offY=offY||0;
if (offX<0) {offX=offX-Math.floor(offX/iW)*iW;} if (offX>0) {offX=(offX%iW)-iW;}
if (offY<0) {offY=offY-Math.floor(offY/iH)*iH;} if (offY>0) {offY=(offY%iH)-iH;}
for (var y=offY;y<H;y+=iH){for (var x=offX;x<W;x+=iW){this.drawImage(img,X+x,Y+y,iW,iH);}}
}
}
var OldCanvasDrawImage=CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage=function()
{
//only draw the image if it's loaded
if (arguments[0].alt!='blank') OldCanvasDrawImage.apply(this,arguments);
}
if (!document.hasFocus) document.hasFocus=function(){return document.hidden;};//for Opera
function AddEvent(html_element, event_name, event_function)
{
if(html_element.attachEvent) html_element.attachEvent("on" + event_name, function() {event_function.call(html_element);});
else if(html_element.addEventListener) html_element.addEventListener(event_name, event_function, false);
}
function FireEvent(el, etype)
{
if (el.fireEvent)
{el.fireEvent('on'+etype);}
else
{
var evObj=document.createEvent('Events');
evObj.initEvent(etype,true,false);
el.dispatchEvent(evObj);
}
}
var Loader=function()//asset-loading system
{
this.loadingN=0;
this.assetsN=0;
this.assets=[];
this.assetsLoading=[];
this.assetsLoaded=[];
this.domain='';
this.loaded=0;//callback
this.doneLoading=0;
this.blank=document.createElement('canvas');
this.blank.width=8;
this.blank.height=8;
this.blank.alt='blank';
this.Load=function(assets)
{
for (var i in assets)
{
this.loadingN++;
this.assetsN++;
if (!this.assetsLoading[assets[i]] && !this.assetsLoaded[assets[i]])
{
var img=new Image();
img.src=this.domain+assets[i];
img.alt=assets[i];
img.onload=bind(this,this.onLoad);
this.assets[assets[i]]=img;
this.assetsLoading.push(assets[i]);
}
}
}
this.Replace=function(old,newer)
{
if (this.assets[old])
{
var img=new Image();
if (newer.indexOf('http')!=-1) img.src=newer;
else img.src=this.domain+newer;
img.alt=newer;
img.onload=bind(this,this.onLoad);
this.assets[old]=img;
}
}
this.onLoadReplace=function()
{
}
this.onLoad=function(e)
{
this.assetsLoaded.push(e.target.alt);
this.assetsLoading.splice(this.assetsLoading.indexOf(e.target.alt),1);
this.loadingN--;
if (this.doneLoading==0 && this.loadingN<=0 && this.loaded!=0)
{
this.doneLoading=1;
this.loaded();
}
}
this.getProgress=function()
{
return (1-this.loadingN/this.assetsN);
}
}
var Pic=function(what)
{
if (Game.Loader.assetsLoaded.indexOf(what)!=-1) return Game.Loader.assets[what];
else if (Game.Loader.assetsLoading.indexOf(what)==-1) Game.Loader.Load([what]);
return Game.Loader.blank;
}
var Sounds=[];
var OldPlaySound=function(url,vol)
{
var volume=1;
if (vol!==undefined) volume=vol;
if (!Game.volume || volume==0) return 0;
if (!Sounds[url]) {Sounds[url]=new Audio(url);Sounds[url].onloadeddata=function(e){e.target.volume=Math.pow(volume*Game.volume/100,2);}}
else if (Sounds[url].readyState>=2) {Sounds[url].currentTime=0;Sounds[url].volume=Math.pow(volume*Game.volume/100,2);}
Sounds[url].play();
}
var SoundInsts=[];
var SoundI=0;
for (var i=0;i<12;i++){SoundInsts[i]=new Audio();}
var pitchSupport=false;
//note : Chrome turns out to not support webkitPreservesPitch despite the specifications claiming otherwise, and Firefox clips some short sounds when changing playbackRate, so i'm turning the feature off completely until browsers get it together
//if (SoundInsts[0].preservesPitch || SoundInsts[0].mozPreservesPitch || SoundInsts[0].webkitPreservesPitch) pitchSupport=true;
var PlaySound=function(url,vol,pitchVar)
{
//url : the url of the sound to play (will be cached so it only loads once)
//vol : volume between 0 and 1 (multiplied by game volume setting); defaults to 1 (full volume)
//(DISABLED) pitchVar : pitch variance in browsers that support it (Firefox only at the moment); defaults to 0.05 (which means pitch can be up to -5% or +5% anytime the sound plays)
var volume=1;
var pitchVar=(typeof pitchVar==='undefined')?0.05:pitchVar;
var rate=1+(Math.random()*2-1)*pitchVar;
if (typeof vol!=='undefined') volume=vol;
if (!Game.volume || volume==0) return 0;
if (!Sounds[url])
{
//sound isn't loaded, cache it
Sounds[url]=new Audio(url);
Sounds[url].onloadeddata=function(e){PlaySound(url,vol,pitchVar);}
}
else if (Sounds[url].readyState>=2)
{
var sound=SoundInsts[SoundI];
SoundI++;
if (SoundI>=12) SoundI=0;
sound.src=Sounds[url].src;
//sound.currentTime=0;
sound.volume=Math.pow(volume*Game.volume/100,2);
if (pitchSupport && rate!=0)
{
sound.preservesPitch=false;
sound.mozPreservesPitch=false;
sound.webkitPreservesPitch=false;
sound.playbackRate=rate;
}
sound.play();
}
}
if (!Date.now){Date.now=function now() {return new Date().getTime();};}
triggerAnim=function(element,anim)
{
if (!element) return;
element.classList.remove(anim);
void element.offsetWidth;
element.classList.add(anim);
};
var debugStr='';
var Debug=function(what)
{
if (!debugStr) debugStr=what;
else debugStr+='; '+what;
}
var Timer={};
Timer.t=Date.now();
Timer.labels=[];
Timer.smoothed=[];
Timer.reset=function()
{
Timer.labels=[];
Timer.t=Date.now();
}
Timer.track=function(label)
{
if (!Game.sesame) return;
var now=Date.now();
if (!Timer.smoothed[label]) Timer.smoothed[label]=0;
Timer.smoothed[label]+=((now-Timer.t)-Timer.smoothed[label])*0.1;
Timer.labels[label]='<div style="padding-left:8px;">'+label+' : '+Math.round(Timer.smoothed[label])+'ms</div>';
Timer.t=now;
}
Timer.clean=function()
{
if (!Game.sesame) return;
var now=Date.now();
Timer.t=now;
}
Timer.say=function(label)
{
if (!Game.sesame) return;
Timer.labels[label]='<div style="border-top:1px solid #ccc;">'+label+'</div>';
}
/*=====================================================================================
GAME INITIALIZATION
=======================================================================================*/
var Game={};
Game.Launch=function()
{
Game.version=VERSION;
Game.beta=BETA;
if (window.location.href.indexOf('/beta')>-1) Game.beta=1;
Game.mobile=0;
Game.touchEvents=0;
//if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) Game.mobile=1;
//if (Game.mobile) Game.touchEvents=1;
//if ('ontouchstart' in document.documentElement) Game.touchEvents=1;
var css=document.createElement('style');
css.type='text/css';
css.innerHTML='body .icon,body .crate,body .usesIcon{background-image:url(img/icons.png?v='+Game.version+');}';
document.head.appendChild(css);
Game.baseSeason='';//halloween, christmas, valentines, fools, easter
//automatic season detection (might not be 100% accurate)
var day=Math.floor((new Date()-new Date(new Date().getFullYear(),0,0))/(1000*60*60*24));
if (day>=41 && day<=46) Game.baseSeason='valentines';
else if (day>=90 && day<=92) Game.baseSeason='fools';
else if (day>=304-7 && day<=304) Game.baseSeason='halloween';
else if (day>=349 && day<=365) Game.baseSeason='christmas';
else
{
//easter is a pain goddamn
var easterDay=function(Y){var C = Math.floor(Y/100);var N = Y - 19*Math.floor(Y/19);var K = Math.floor((C - 17)/25);var I = C - Math.floor(C/4) - Math.floor((C - K)/3) + 19*N + 15;I = I - 30*Math.floor((I/30));I = I - Math.floor(I/28)*(1 - Math.floor(I/28)*Math.floor(29/(I + 1))*Math.floor((21 - N)/11));var J = Y + Math.floor(Y/4) + I + 2 - C + Math.floor(C/4);J = J - 7*Math.floor(J/7);var L = I - J;var M = 3 + Math.floor((L + 40)/44);var D = L + 28 - 31*Math.floor(M/4);return new Date(Y,M-1,D);}(new Date().getFullYear());
easterDay=Math.floor((easterDay-new Date(easterDay.getFullYear(),0,0))/(1000*60*60*24));
if (day>=easterDay-7 && day<=easterDay) Game.baseSeason='easter';
}
Game.updateLog=
'<div class="selectable">'+
'<div class="section">Info</div>'+
'<div class="subsection">'+
'<div class="title">About</div>'+
'<div class="listing">Cookie Clicker is a javascript game by <a href="http://orteil.dashnet.org" target="_blank">Orteil</a> and <a href="http://dashnet.org" target="_blank">Opti</a>.</div>'+
//'<div class="listing">We have an <a href="https://discordapp.com/invite/cookie" target="_blank">official Discord</a>, as well as a <a href="http://forum.dashnet.org" target="_blank">forum</a>; '+
'<div class="listing">We have an <a href="https://discordapp.com/invite/cookie" target="_blank">official Discord</a>; '+
'if you\'re looking for help, you may also want to visit the <a href="http://www.reddit.com/r/CookieClicker" target="_blank">subreddit</a> '+
'or the <a href="http://cookieclicker.wikia.com/wiki/Cookie_Clicker_Wiki" target="_blank">wiki</a>.</div>'+
'<div class="listing">News and teasers are usually posted on my <a href="http://orteil42.tumblr.com/" target="_blank">tumblr</a> and <a href="http://twitter.com/orteil42" target="_blank">twitter</a>.</div>'+
'<div class="listing" id="supportSection"><b style="color:#fff;opacity:1;">Cookie Clicker is 100% free, forever.</b> Want to support us so we can keep developing games? Here\'s some ways you can help :<div style="margin:4px 12px;line-height:150%;">'+
'<br>• support us on <a href="https://www.patreon.com/dashnet" target="_blank" class="highlightHover" style="background:#f86754;box-shadow:0px 0px 0px 1px #c52921 inset,0px 2px 0px #ff966d inset;text-shadow:0px -1px 0px #ff966d,0px 1px 0px #c52921;text-decoration:none;color:#fff;font-weight:bold;padding:1px 4px;">Patreon</a> <span style="opacity:0.5;">(there\'s perks!)</span>'+
'<br>• <form target="_blank" action="https://www.paypal.com/cgi-bin/webscr" method="post" id="donate"><input type="hidden" name="cmd" value="_s-xclick"><input type="hidden" name="hosted_button_id" value="BBN2WL3TC6QH4"><input type="submit" id="donateButton" value="donate" name="submit" alt="PayPal — The safer, easier way to pay online."><img alt="" border="0" src="https://www.paypalobjects.com/nl_NL/i/scr/pixel.gif" width="1" height="1"></form> to our PayPal'+
'<br>• disable your adblocker<br>• check out our <a href="http://www.redbubble.com/people/dashnet" target="_blank">rad cookie shirts, hoodies and stickers</a>!<br>• (if you want!)</div></div>'+
'<div class="listing warning">Note : if you find a new bug after an update and you\'re using a 3rd-party add-on, make sure it\'s not just your add-on causing it!</div>'+
'<div class="listing warning">Warning : clearing your browser cache or cookies <small>(what else?)</small> will result in your save being wiped. Export your save and back it up first!</div>'+
'</div><div class="subsection">'+
'<div class="title">Version history</div>'+
'</div><div class="subsection update small">'+
'<div class="title">01/04/2019 - 2.019 (the "this year" update)</div>'+
'<div class="listing">• game has been renamed to "Cookie Clicker" to avoid confusion</div>'+
'<div class="listing">• can now click the big cookie to generate cookies for free</div>'+
'<div class="listing">• removed fall damage</div>'+
'<div class="listing">• fixed various typos : player\'s name is now correctly spelled as "[bakeryName]"</div>'+
'<div class="listing">• removed all references to computer-animated movie <i style="font-style:italic;">Hoodwinked!</i> (2005)</div>'+
'<div class="listing">• went back in time and invented cookies and computer mice, ensuring Cookie Clicker would one day come to exist</div>'+
'<div class="listing">• game now fully compliant with Geneva Conventions</div>'+
'<div class="listing">• dropped support for TI-84 version</div>'+
'<div class="listing">• released a low-res retro version of the game, playable here : <a href="http://orteil.dashnet.org/experiments/cookie/" target="_blank">orteil.dashnet.org/experiments/cookie</a></div>'+
'<div class="listing">• updated version number</div>'+
'</div><div class="subsection update small">'+
'<div class="title">05/03/2019 - cookies for days</div>'+
'<div class="listing">• added over 20 new cookies, all previously suggested by our supporters on <a href="https://www.patreon.com/dashnet" target="_blank">Patreon</a></div>'+
'<div class="listing">• added 2 heavenly upgrades</div>'+
'<div class="listing">• the Golden goose egg now counts as a golden cookie upgrade for Residual luck purposes</div>'+
'<div class="listing">• golden sugar lumps now either double your cookies, or give you 24 hours of your CpS, whichever is lowest (previously was doubling cookies with no cap)</div>'+
'<div class="listing">• the amount of heralds is now saved with your game, and is used to compute offline CpS the next time the game is loaded; previously, on page load, the offline calculation assumed heralds to be 0</div>'+
'<div class="listing">• added a system to counteract the game freezing up (and not baking cookies) after being inactive for a long while on slower computers; instead, this will now trigger sleep mode, during which you still produce cookies as if the game was closed; to enable this feature, use the "Sleep mode timeout" option in the settings</div>'+
'<div class="listing">• vaulting upgrades is now done with shift-click, as ctrl-click was posing issues for Mac browsers</div>'+
'<div class="listing">• made tooltips for building CpS boosts from synergies hopefully clearer</div>'+
'<div class="listing">• fixed an exploit with gambler\'s fever dream working across exports and ascensions</div>'+
'<div class="listing">• can now hide tooltips in the garden by keeping the shift key pressed to make it easier to see where you\'re planting</div>'+
'<div class="listing">• fixed a bug with golden cookies/reindeer not disappearing properly in some circumstances</div>'+
'<div class="listing">• the Dragon\'s Curve aura should now properly make sugar lumps twice as weird</div>'+
'<div class="listing">• the ctrl key should less often register incorrectly as pressed</div>'+
'<div class="listing">• added a new ad slot in the top-right, as while our playerbase is strong and supportive as ever, our ad revenue sometimes fluctuates badly; we may remove the ad again should our income stabilize</div>'+
'<div class="listing">• made a few adjustments to make the game somewhat playable in mobile browsers; it\'s not perfect and can get buggy, but it\'s functional! (you may need to zoom out or scroll around to view the game properly)</div>'+
'<div class="listing">• speaking of which, we also got some good progress on the mobile app version (built from scratch for mobile), so stay tuned!</div>'+
'</div><div class="subsection update">'+
'<div class="title">25/10/2018 - feedback loop</div>'+
'<div class="listing">• added a new building</div>'+
'<div class="listing">• launched our <a href="https://www.patreon.com/dashnet" class="orangeLink" target="_blank">Patreon</a> <span style="font-size:80%;">(the link is orange so you\'ll notice it!)</span></div>'+
'<div class="listing">• added a bunch of new heavenly upgrades, one of which ties into our Patreon but benefits everyone (this is still experimental!)</div>'+
'<div class="listing">• when hovering over grandmas, you can now see their names and ages</div>'+
'<div class="listing">• "make X cookies just from Y" requirements are now higher</div>'+
'<div class="listing">• tweaked the prices of some heavenly upgrades to better fit the current cookie economy (it turns out billions of heavenly chips is now very achievable)</div>'+
'<div class="listing">• building tooltips now display what % of CpS they contribute through synergy upgrades</div>'+
'<div class="listing">• queenbeets now give up to 4% of bank, down from 6%</div>'+
'<div class="listing">• among other things, season switches now display how many seasonal upgrades you\'re missing, and permanent upgrade slots now display the name of the slotted upgrade</div>'+
'<div class="listing">• season switches have reworked prices</div>'+
'<div class="listing">• season switches can now be cancelled by clicking them again</div>'+
'<div class="listing">• can no longer accidentally click wrinklers through other elements</div>'+
'<div class="listing">• sugar frenzy now triples your CpS for an hour instead of doubling it</div>'+
'<div class="listing">• this text is now selectable</div>'+
'<div class="listing">• progress on dungeons minigame is still very much ongoing</div>'+
'</div><div class="subsection update small">'+
'<div class="title">08/08/2018 - hey now</div>'+
'<div class="listing">• Cookie Clicker somehow turns 5, going against doctors\' most optimistic estimates</div>'+
'<div class="listing">• added a new tier of building achievements, all named after Smash Mouth\'s classic 1999 hit "All Star"</div>'+
'<div class="listing">• added a new tier of building upgrades, all named after nothing in particular</div>'+
'<div class="listing">• <b>to our players :</b> thank you so much for sticking with us all those years and allowing us to keep making the dumbest game known to mankind</div>'+
'<div class="listing">• resumed work on the dungeons minigame</div>'+
'</div><div class="subsection update small">'+
'<div class="title">01/08/2018 - buy buy buy</div>'+
'<div class="listing">• added a heavenly upgrade that lets you buy all your upgrades instantly</div>'+
'<div class="listing">• added a heavenly upgrade that lets you see upgrade tiers (feature was previously removed due to being confusing)</div>'+
'<div class="listing">• added a new wrinkler-related heavenly upgrade</div>'+
'<div class="listing">• added a new upgrade tier</div>'+
'<div class="listing">• added a couple new cookies and achievements</div>'+
'<div class="listing">• new "extra buttons" setting; turning it on adds buttons that let you minimize buildings</div>'+
'<div class="listing">• new "lump confirmation" setting; turning it on will show a confirmation prompt when you spend sugar lumps</div>'+
'<div class="listing">• buildings now sell back for 25% of their current price (down from 50%); Earth Shatterer modified accordingly, now gives back 50% (down from 85%)</div>'+
'<div class="listing">• farm soils now unlock correctly based on current amount of farms</div>'+
'<div class="listing">• cheapcaps have a new exciting nerf</div>'+
'<div class="listing">• wrinklegill spawns a bunch more</div>'+
'<div class="listing">• can now ctrl-shift-click on "Harvest all" to only harvest mature, non-immortal plants</div>'+
'<div class="listing">• added a new rare type of sugar lump</div>'+
'</div><div class="subsection update small">'+
'<div class="title">20/04/2018 - weeding out some bugs</div>'+
'<div class="listing">• golden clovers and wrinklegills should spawn a bit more often</div>'+
'<div class="listing">• cronerice matures a lot sooner</div>'+
'<div class="listing">• mature elderworts stay mature after reloading</div>'+
'<div class="listing">• garden interface occupies space more intelligently</div>'+
'<div class="listing">• seed price displays should be better behaved with short numbers disabled</div>'+
'<div class="listing">• minigame animations are now turned off if using the "Fancy graphics" option is disabled</div>'+
'<div class="listing">• CpS achievement requirements were dialed down a wee tad</div>'+
'</div><div class="subsection update small">'+
'<div class="title">19/04/2018 - garden patch</div>'+
'<div class="listing">• upgrades dropped by garden plants now stay unlocked forever (but drop much more rarely)</div>'+
'<div class="listing">• garden sugar lump refill now also makes plants spread and mutate 3 times more during the bonus tick</div>'+
'<div class="listing">• a few new upgrades</div>'+
'<div class="listing">• a couple bug fixes and rephrasings</div>'+
'</div><div class="subsection update">'+
'<div class="title">18/04/2018 - your garden-variety update</div>'+
'<div class="listing">• added the garden, a minigame unlocked by having at least level 1 farms</div>'+
'<div class="listing">• added a little arrow and a blinky label to signal the game has updated since you last played it (hi!)</div>'+
'<div class="listing">• new cookies, milk flavors and achievements</div>'+
'<div class="listing">• sugar lumps are now unlocked whenever you\'ve baked at least a billion cookies, instead of on your first ascension</div>'+
'<div class="listing">• sugar lump type now saves correctly</div>'+
'<div class="listing">• minigame sugar lump refills can now only be done every 15 minutes (timer shared across all minigames)</div>'+
'<div class="listing">• CpS achievements now have steeper requirements</div>'+
'<div class="listing">• golden cookies now last 5% shorter for every other golden cookie on the screen</div>'+
'<div class="listing">• the game now remembers which minigames are closed or open</div>'+
'<div class="listing">• added a popup that shows when a season starts (so people won\'t be so confused about "the game looking weird today")</div>'+
'<div class="listing">• permanent upgrade slots now show a tooltip for the selected upgrade</div>'+
'<div class="listing">• finally fixed the save corruption bug, hopefully</div>'+
'</div><div class="subsection update small">'+
'<div class="title">24/02/2018 - sugar coating</div>'+
'<div class="listing">• added link to <a href="https://discordapp.com/invite/cookie" target="_blank">official Discord server</a></div>'+
'<div class="listing">• felt weird about pushing an update without content so :</div>'+
'<div class="listing">• added a handful of new cookies</div>'+
'<div class="listing">• added 3 new heavenly upgrades</div>'+
'<div class="listing">• short numbers should now be displayed up to novemnonagintillions</div>'+
'<div class="listing">• cookie chains no longer spawn from the Force the Hand of Fate spell</div>'+
'<div class="listing">• bigger, better Cookie Clicker content coming later this year</div>'+
'</div><div class="subsection update">'+
'<div class="title">08/08/2017 - 4 more years</div>'+
'<div class="listing">• new building : Chancemakers</div>'+
'<div class="listing">• new milk, new kittens, new dragon aura, new cookie, new upgrade tier</div>'+
'<div class="listing">• buffs no longer affect offline CpS</div>'+
'<div class="listing">• Godzamok\'s hunger was made less potent (this is a nerf, very sorry)</div>'+
'<div class="listing">• grimoire spell costs and maximum magic work differently</div>'+
'<div class="listing">• Spontaneous Edifice has been reworked</div>'+
'<div class="listing">• changed unlock levels and prices for some cursor upgrades</div>'+
'<div class="listing">• fixed buggy pantheon slots, hopefully</div>'+
'<div class="listing">• fixed "Legacy started a long while ago" showing as "a few seconds ago"</div>'+
'<div class="listing">• Cookie Clicker just turned 4. Thank you for sticking with us this long!</div>'+
'</div><div class="subsection update">'+
'<div class="title">15/07/2017 - the spiritual update</div>'+
'<div class="listing">• implemented sugar lumps, which start coalescing if you\'ve ascended at least once and can be used as currency for special things</div>'+
'<div class="listing">• buildings can now level up by using sugar lumps in the main buildings display, permanently boosting their CpS</div>'+
'<div class="listing">• added two new features unlocked by levelling up their associated buildings, Temples and Wizard towers; more building-related minigames will be implemented in the future</div>'+
'<div class="listing">• active buffs are now saved</div>'+
'<div class="listing">• the background selector upgrade is now functional</div>'+
'<div class="listing">• the top menu no longer scrolls with the rest</div>'+
'<div class="listing">• timespans are written nicer</div>'+
'<div class="listing">• Dragonflights now tend to supercede Click frenzies, you will rarely have both at the same time</div>'+
'<div class="listing">• some old bugs were phased out and replaced by new ones</div>'+
'</div><div class="subsection update small">'+
'<div class="title">24/07/2016 - golden cookies overhaul</div>'+
'<div class="listing">• golden cookies and reindeer now follow a new system involving explicitly defined buffs</div>'+
'<div class="listing">• a bunch of new golden cookie effects have been added</div>'+
'<div class="listing">• CpS gains from eggs are now multiplicative</div>'+
'<div class="listing">• shiny wrinklers are now saved</div>'+
'<div class="listing">• reindeer have been rebalanced ever so slightly</div>'+
'<div class="listing">• added a new cookie upgrade near the root of the heavenly upgrade tree; this is intended to boost early ascensions and speed up the game as a whole</div>'+
'<div class="listing">• due to EU legislation, implemented a warning message regarding browser cookies; do understand that the irony is not lost on us</div>'+
'</div><div class="subsection update">'+
'<div class="title">08/02/2016 - legacy</div>'+
'<div class="listing"><b>Everything that was implemented during the almost 2-year-long beta has been added to the live game. To recap :</b></div>'+
'<div class="listing">• 3 new buildings : banks, temples, and wizard towers; these have been added in-between existing buildings and as such, may disrupt some building-related achievements</div>'+
'<div class="listing">• the ascension system has been redone from scratch, with a new heavenly upgrade tree</div>'+
'<div class="listing">• mysterious new features such as angel-powered offline progression, challenge runs, and a cookie dragon</div>'+
'<div class="listing">• sounds have been added (can be disabled in the options)</div>'+
'<div class="listing">• heaps of rebalancing and bug fixes</div>'+
'<div class="listing">• a couple more upgrades and achievements, probably</div>'+
'<div class="listing">• fresh new options to further customize your cookie-clicking experience</div>'+
'<div class="listing">• quality-of-life improvements : better bulk-buy, better switches etc</div>'+
'<div class="listing">• added some <a href="http://en.wikipedia.org/wiki/'+choose(['Krzysztof_Arciszewski','Eustachy_Sanguszko','Maurycy_Hauke','Karol_Turno','Tadeusz_Kutrzeba','Kazimierz_Fabrycy','Florian_Siwicki'])+'" target="_blank">general polish</a></div>'+/* i liked this dumb pun too much to let it go unnoticed */
'<div class="listing">• tons of other little things we can\'t even remember right now</div>'+
'<div class="listing">Miss the old version? Your old save was automatically exported <a href="http://orteil.dashnet.org/cookieclicker/v10466/" target="_blank">here</a>!</div>'+
'</div><div class="subsection update small">'+
'<div class="title">05/02/2016 - legacy beta, more fixes</div>'+
'<div class="listing">• added challenge modes, which can be selected when ascending (only 1 for now : "Born again")</div>'+
'<div class="listing">• changed the way bulk-buying and bulk-selling works</div>'+
'<div class="listing">• more bugs ironed out</div>'+
'</div><div class="subsection update">'+
'<div class="title">03/02/2016 - legacy beta, part III</div>'+
'<div class="listing warning">• Not all bugs have been fixed, but everything should be much less broken.</div>'+
'<div class="listing">• Additions'+
'<div style="opacity:0.8;margin-left:12px;">'+
'-a few more achievements<br>'+
'-new option for neat, but slow CSS effects (disabled by default)<br>'+
'-new option for a less grating cookie sound (enabled by default)<br>'+
'-new option to bring back the boxes around icons in the stats screen<br>'+
'-new buttons for saving and loading your game to a text file<br>'+
'</div>'+
'</div>'+
'<div class="listing">• Changes'+
'<div style="opacity:0.8;margin-left:12px;">'+
'-early game should be a bit faster and very late game was kindly asked to tone it down a tad<br>'+
'-dragonflight should be somewhat less ridiculously overpowered<br>'+
'-please let me know if the rebalancing was too heavy or not heavy enough<br>'+
'-santa and easter upgrades now depend on Santa level and amount of eggs owned, respectively, instead of costing several minutes worth of CpS<br>'+
'-cookie upgrades now stack multiplicatively rather than additively<br>'+
'-golden switch now gives +50% CpS, and residual luck is +10% CpS per golden cookie upgrade (up from +25% and +1%, respectively)<br>'+
'-lucky cookies and cookie chain payouts have been modified a bit, possibly for the better, who knows!<br>'+
'-wrinklers had previously been reduced to a maximum of 8 (10 with a heavenly upgrade), but are now back to 10 (12 with the upgrade)<br>'+
/*'-all animations are now handled by requestAnimationFrame(), which should hopefully help make the game less resource-intensive<br>'+*/
'-an ascension now only counts for achievement purposes if you earned at least 1 prestige level from it<br>'+
'-the emblematic Cookie Clicker font (Kavoon) was bugged in Firefox, and has been replaced with a new font (Merriweather)<br>'+
'-the mysterious wrinkly creature is now even rarer, but has a shadow achievement tied to it<br>'+
'</div>'+
'</div>'+
'<div class="listing">• Fixes'+
'<div style="opacity:0.8;margin-left:12px;">'+
'-prestige now grants +1% CpS per level as intended, instead of +100%<br>'+
'-heavenly chips should no longer add up like crazy when you ascend<br>'+
'-upgrades in the store should no longer randomly go unsorted<br>'+
'-window can be resized to any size again<br>'+
'-the "Stats" and "Options" buttons have been swapped again<br>'+
'-the golden cookie sound should be somewhat clearer<br>'+
'-the ascend screen should be less CPU-hungry<br>'+
'</div>'+
'</div>'+
'</div><div class="subsection update">'+
'<div class="title">20/12/2015 - legacy beta, part II</div>'+
'<div class="listing warning">• existing beta saves have been wiped due to format inconsistencies and just plain broken balance; you\'ll have to start over from scratch - which will allow you to fully experience the update and find all the awful little bugs that no doubt plague it</div>'+
'<div class="listing warning">• importing your save from the live version is also fine</div>'+
'<div class="listing">• we took so long to make this update, Cookie Clicker turned 2 years old in the meantime! Hurray!</div>'+
'<div class="listing">• heaps of new upgrades and achievements</div>'+
'<div class="listing">• fixed a whole bunch of bugs</div>'+
'<div class="listing">• did a lot of rebalancing</div>'+
'<div class="listing">• reworked heavenly chips and heavenly cookies (still experimenting, will probably rebalance things further)</div>'+
'<div class="listing">• you may now unlock a dragon friend</div>'+
'<div class="listing">• switches and season triggers now have their own store section</div>'+
'<div class="listing">• ctrl-s and ctrl-o now save the game and open the import menu, respectively</div>'+
'<div class="listing">• added some quick sounds, just as a test</div>'+
'<div class="listing">• a couple more options</div>'+
'<div class="listing">• even more miscellaneous changes and additions</div>'+
'</div><div class="subsection update">'+
'<div class="title">25/08/2014 - legacy beta, part I</div>'+
'<div class="listing">• 3 new buildings</div>'+
'<div class="listing">• price and CpS curves revamped</div>'+
'<div class="listing">• CpS calculations revamped; cookie upgrades now stack multiplicatively</div>'+
'<div class="listing">• prestige system redone from scratch, with a whole new upgrade tree</div>'+
'<div class="listing">• added some <a href="http://en.wikipedia.org/wiki/'+choose(['Krzysztof_Arciszewski','Eustachy_Sanguszko','Maurycy_Hauke','Karol_Turno','Tadeusz_Kutrzeba','Kazimierz_Fabrycy','Florian_Siwicki'])+'" target="_blank">general polish</a></div>'+
'<div class="listing">• tons of other miscellaneous fixes and additions</div>'+
'<div class="listing">• Cookie Clicker is now 1 year old! (Thank you guys for all the support!)</div>'+
'<div class="listing warning">• Note : this is a beta; you are likely to encounter bugs and oversights. Feel free to send me feedback if you find something fishy!</div>'+
'</div><div class="subsection update small">'+
'<div class="title">18/05/2014 - better late than easter</div>'+
'<div class="listing">• bunnies and eggs, somehow</div>'+
'<div class="listing">• prompts now have keyboard shortcuts like system prompts would</div>'+
'<div class="listing">• naming your bakery? you betcha</div>'+
'<div class="listing">• "Fast notes" option to make all notifications close faster; new button to close all notifications</div>'+
'<div class="listing">• the dungeons beta is now available on <a href="http://orteil.dashnet.org/cookieclicker/betadungeons" target="_blank">/betadungeons</a></div>'+
'</div><div class="subsection update small">'+
'<div class="title">09/04/2014 - nightmare in heaven</div>'+
'<div class="listing">• broke a thing; heavenly chips were corrupted for some people</div>'+
'<div class="listing">• will probably update to /beta first in the future</div>'+
'<div class="listing">• sorry again</div>'+
'</div><div class="subsection update small">'+
'<div class="title">09/04/2014 - quality of life</div>'+
'<div class="listing">• new upgrade and achievement tier</div>'+
'<div class="listing">• popups and prompts are much nicer</div>'+
'<div class="listing">• tooltips on buildings are more informative</div>'+
'<div class="listing">• implemented a simplified version of the <a href="https://github.com/Icehawk78/FrozenCookies" target="_blank">Frozen Cookies</a> add-on\'s short number formatting</div>'+
'<div class="listing">• you can now buy 10 and sell all of a building at a time</div>'+
'<div class="listing">• tons of optimizations and subtler changes</div>'+
'<div class="listing">• you can now <a href="http://orteil.dashnet.org/cookies2cash/" target="_blank">convert your cookies to cash</a>!</div>'+
'</div><div class="subsection update small">'+
'<div class="title">05/04/2014 - pity the fool</div>'+
'<div class="listing">• wrinklers should now be saved so you don\'t have to pop them everytime you refresh the game</div>'+
'<div class="listing">• you now properly win 1 cookie upon reaching 10 billion cookies and making it on the local news</div>'+
'<div class="listing">• miscellaneous fixes and tiny additions</div>'+
'<div class="listing">• added a few very rudimentary mod hooks</div>'+
'<div class="listing">• the game should work again in Opera</div>'+
'<div class="listing">• don\'t forget to check out <a href="http://orteil.dashnet.org/randomgen/" target="_blank">RandomGen</a>, our all-purpose random generator maker!</div>'+
'</div><div class="subsection update small">'+
'<div class="title">01/04/2014 - fooling around</div>'+
'<div class="listing">• it\'s about time : Cookie Clicker has turned into the much more realistic Cookie Baker</div>'+
'<div class="listing">• season triggers are cheaper and properly unlock again when they run out</div>'+
'<div class="listing">• buildings should properly unlock (reminder : building unlocking is completely cosmetic and does not change the gameplay)</div>'+
'</div><div class="subsection update small">'+
'<div class="title">14/02/2014 - lovely rainbowcalypse</div>'+
'<div class="listing">• new building (it\'s been a while). More to come!</div>'+
'<div class="listing">• you can now trigger seasonal events to your heart\'s content (upgrade unlocks at 5000 heavenly chips)</div>'+
'<div class="listing">• new ultra-expensive batch of seasonal cookie upgrades you\'ll love to hate</div>'+
'<div class="listing">• new timer bars for golden cookie buffs</div>'+
'<div class="listing">• buildings are now hidden when you start out and appear as they become available</div>'+
'<div class="listing">• technical stuff : the game is now saved through localstorage instead of browser cookies, therefore ruining a perfectly good pun</div>'+
'</div><div class="subsection update small">'+
'<div class="title">22/12/2013 - merry fixmas</div>'+
'<div class="listing">• some issues with the christmas upgrades have been fixed</div>'+
'<div class="listing">• reindeer cookie drops are now more common</div>'+
'<div class="listing">• reindeers are now reindeer</div>'+
'</div><div class="subsection update">'+
'<div class="title">20/12/2013 - Christmas is here</div>'+
'<div class="listing">• there is now a festive new evolving upgrade in store</div>'+
'<div class="listing">• reindeer are running amok (catch them if you can!)</div>'+
'<div class="listing">• added a new option to warn you when you close the window, so you don\'t lose your un-popped wrinklers</div>'+
'<div class="listing">• also added a separate option for displaying cursors</div>'+
'<div class="listing">• all the Halloween features are still there (and having the Spooky cookies achievements makes the Halloween cookies drop much more often)</div>'+
'<div class="listing">• oh yeah, we now have <a href="http://www.redbubble.com/people/dashnet" target="_blank">Cookie Clicker shirts, stickers and hoodies</a>! (they\'re really rad)</div>'+
'</div><div class="subsection update small">'+
'<div class="title">29/10/2013 - spooky update</div>'+
'<div class="listing">• the Grandmapocalypse now spawns wrinklers, hideous elderly creatures that damage your CpS when they reach your big cookie. Thankfully, you can click on them to make them explode (you\'ll even gain back the cookies they\'ve swallowed - with interest!).</div>'+
'<div class="listing">• wrath cookie now 27% spookier</div>'+
'<div class="listing">• some other stuff</div>'+
'<div class="listing">• you should totally go check out <a href="http://candybox2.net/" target="_blank">Candy Box 2</a>, the sequel to the game that inspired Cookie Clicker</div>'+
'</div><div class="subsection update small">'+
'<div class="title">15/10/2013 - it\'s a secret</div>'+
'<div class="listing">• added a new heavenly upgrade that gives you 5% of your heavenly chips power for 11 cookies (if you purchased the Heavenly key, you might need to buy it again, sorry)</div>'+
'<div class="listing">• golden cookie chains should now work properly</div>'+
'</div><div class="subsection update small">'+
'<div class="title">15/10/2013 - player-friendly</div>'+
'<div class="listing">• heavenly upgrades are now way, way cheaper</div>'+
'<div class="listing">• tier 5 building upgrades are 5 times cheaper</div>'+
'<div class="listing">• cursors now just plain disappear with Fancy Graphics off, I might add a proper option to toggle only the cursors later</div>'+
'<div class="listing">• warning : the Cookie Monster add-on seems to be buggy with this update, you might want to wait until its programmer updates it</div>'+
'</div><div class="subsection update small">'+
'<div class="title">15/10/2013 - a couple fixes</div>'+
'<div class="listing">• golden cookies should no longer spawn embarrassingly often</div>'+
'<div class="listing">• cursors now stop moving if Fancy Graphics is turned off</div>'+
'</div><div class="subsection update small">'+
'<div class="title">14/10/2013 - going for the gold</div>'+
'<div class="listing">• golden cookie chains work a bit differently</div>'+
'<div class="listing">• golden cookie spawns are more random</div>'+
'<div class="listing">• CpS achievements are no longer affected by golden cookie frenzies</div>'+
'<div class="listing">• revised cookie-baking achievement requirements</div>'+
'<div class="listing">• heavenly chips now require upgrades to function at full capacity</div>'+
'<div class="listing">• added 4 more cookie upgrades, unlocked after reaching certain amounts of Heavenly Chips</div>'+
'<div class="listing">• speed baking achievements now require you to have no heavenly upgrades; as such, they have been reset for everyone (along with the Hardcore achievement) to better match their initially intended difficulty</div>'+
'<div class="listing">• made good progress on the mobile port</div>'+
'</div><div class="subsection update small">'+
'<div class="title">01/10/2013 - smoothing it out</div>'+
'<div class="listing">• some visual effects have been completely rewritten and should now run more smoothly (and be less CPU-intensive)</div>'+
'<div class="listing">• new upgrade tier</div>'+
'<div class="listing">• new milk tier</div>'+
'<div class="listing">• cookie chains have different capping mechanics</div>'+
'<div class="listing">• antimatter condensers are back to their previous price</div>'+
'<div class="listing">• heavenly chips now give +2% CpS again (they will be extensively reworked in the future)</div>'+
'<div class="listing">• farms have been buffed a bit (to popular demand)</div>'+
'<div class="listing">• dungeons still need a bit more work and will be released soon - we want them to be just right! (you can test an unfinished version in <a href="http://orteil.dashnet.org/cookieclicker/betadungeons/" target="_blank">the beta</a>)</div>'+
'</div><div class="subsection update">'+
'<div class="title">28/09/2013 - dungeon beta</div>'+
'<div class="listing">• from now on, big updates will come through a beta stage first (you can <a href="http://orteil.dashnet.org/cookieclicker/betadungeons/" target="_blank">try it here</a>)</div>'+
'<div class="listing">• first dungeons! (you need 50 factories to unlock them!)</div>'+
'<div class="listing">• cookie chains can be longer</div>'+
'<div class="listing">• antimatter condensers are a bit more expensive</div>'+
'<div class="listing">• heavenly chips now only give +1% cps each (to account for all the cookies made from condensers)</div>'+
'<div class="listing">• added flavor text on all upgrades</div>'+
'</div><div class="subsection update small">'+
'<div class="title">15/09/2013 - anticookies</div>'+
'<div class="listing">• ran out of regular matter to make your cookies? Try our new antimatter condensers!</div>'+
'<div class="listing">• renamed Hard-reset to "Wipe save" to avoid confusion</div>'+
'<div class="listing">• reset achievements are now regular achievements and require cookies baked all time, not cookies in bank</div>'+
'<div class="listing">• heavenly chips have been nerfed a bit (and are now awarded following a geometric progression : 1 trillion for the first, 2 for the second, etc); the prestige system will be extensively reworked in a future update (after dungeons)</div>'+
'<div class="listing">• golden cookie clicks are no longer reset by soft-resets</div>'+
'<div class="listing">• you can now see how long you\'ve been playing in the stats</div>'+
'</div><div class="subsection update small">'+
'<div class="title">08/09/2013 - everlasting cookies</div>'+
'<div class="listing">• added a prestige system - resetting gives you permanent CpS boosts (the more cookies made before resetting, the bigger the boost!)</div>'+
'<div class="listing">• save format has been slightly modified to take less space</div>'+
'<div class="listing">• Leprechaun has been bumped to 777 golden cookies clicked and is now shadow; Fortune is the new 77 golden cookies achievement</div>'+
'<div class="listing">• clicking frenzy is now x777</div>'+
'</div><div class="subsection update small">'+
'<div class="title">04/09/2013 - smarter cookie</div>'+
'<div class="listing">• golden cookies only have 20% chance of giving the same outcome twice in a row now</div>'+
'<div class="listing">• added a golden cookie upgrade</div>'+
'<div class="listing">• added an upgrade that makes pledges last twice as long (requires having pledged 10 times)</div>'+
'<div class="listing">• Quintillion fingers is now twice as efficient</div>'+
'<div class="listing">• Uncanny clicker was really too unpredictable; it is now a regular achievement and no longer requires a world record, just *pretty fast* clicking</div>'+
'</div><div class="subsection update small">'+