[Go]update Go(tizen_2.1)
[samples/web/Go.git] / js / go.js
1 /*
2  * Copyright (c) 2012, Intel Corporation.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 function queryObj(obj) {
11     this.q = obj;
12     this.isNull = this.q?false:true;
13     this.self = this;
14     this.html = function (val) {
15         this.q.innerHTML = val;
16         return this;
17     }
18
19     this.hasClass = function (c_name) {
20         if (this.isNull)
21             return false;
22         return this.q.classList.contains(c_name);
23     }
24
25     this.addClass = function (c_name) {
26         if (this.isNull)
27             return this;
28         var list = this.q.classList;
29         list.add (c_name);
30         return this;
31     }
32
33     this.removeClass = function (c_name) {
34         if (this.isNull)
35             return this;
36         var list = this.q.classList;
37         list.remove (c_name);
38         return this;
39     }
40
41     this.click = function (fun) {
42         if (this.isNull)
43             return this;
44         this.q.onclick = fun;
45         return this;
46     }
47
48     this.attr = function (attr, val) {
49         if (this.isNull)
50             return this;
51         this.q.setAttribute(attr, val);
52         return this;
53     }
54 }
55
56 function $(selector) {
57     var res;
58     if (typeof selector == "string") {
59         res = document.querySelector(selector);
60     } else {
61         res = selector;
62     }
63     return new queryObj(res);
64 }
65
66 function gamesound(src, loop) {
67     var me = this;
68     this.soundobj = new Audio(src);
69     this.soundobj.preload = 'auto';
70     this.enable = false;
71     this.infocus = true;
72     this.loop = (loop == undefined)?false:loop;
73     this.focus = function focus() {
74         if(!me.infocus)
75         {
76             me.infocus = true;
77             if(me.enable&&me.loop)
78                 me.soundobj.play();
79         }
80     };
81     this.blur = function blur() {
82         if(me.infocus)
83         {
84             me.infocus = false;
85             if(me.enable&&me.loop)
86                 me.soundobj.pause();
87         }
88     };
89     window.addEventListener('focus', me.focus, false);
90     window.addEventListener('blur', me.blur, false);
91
92     this.play = function play() {
93         this.enable = true;
94         if(this.infocus)
95             this.soundobj.play();
96     };
97     this.pause = function pause() {
98         this.enable = false;
99         this.soundobj.pause();
100     };
101 }
102
103 var Go = {
104     texture: {
105         'black':'images/GO_BlackPiece_010612_a.png',
106         'black1':'images/GO_BlackPiece_010612_b.png',
107         'black2':'images/GO_BlackPiece_010612_c.png',
108         'white':'images/GO_WhitePiece_010612_a-2.png',
109         'white1': 'images/GO_WhitePiece_010612_b.png',
110         'white2': 'images/GO_WhitePiece_010612_c.png',
111         'uncheck':'images/GO_Checkbox_010612_a.png',
112         'checked':'images/GO_CheckboxChecked_010612_a.png',
113         'board':'images/Go_Board.png',
114     },
115     bounder: 13,
116     boardview:'board',
117     board:[],
118     playButton:'play_button',
119     winMessage:'win_panel',
120     settingPanel:'setting_panel',
121     helpPanel:'help_panel',
122     place: [],
123     directs: [[1,0],[0,1],[0,-1],[-1,0],],
124     player:{},
125     manual:[],
126     isTimer: false,
127     isSound: false,
128     isSetting: false,
129     isStart: false,
130     isStop: false,
131     isPass: false,
132     isExit: false,
133     isRestart: false,
134     isEndMsg: false,
135 };
136
137 Go.init = function(){
138     var welcome = {
139         'black':[[1,3],[1,4],[2,2],[3,2],
140                  [4,2],[5,2],[5,4],[5,5],
141                  [6,2],[6,5],[7,2],[7,5],[8,3],
142                  [8,4],],
143
144         'white':[[1,8],[1,9],[2,7],[2,10],
145                  [3,7],[3,10],[4,7],[4,10],
146                  [5,7],[5,10],[6,7],[6,10],
147                  [7,7],[7,10],[8,8],[8,9],],
148     };
149     for (var i=0; i<this.bounder; i++){
150         var line=new Array();
151         for (var j=0; j<this.bounder; j++){
152             line[j] = 'board';
153         }
154         this.board[i] = line;
155     }
156     for (var color in welcome){
157         var matrix = welcome[color];
158         for (var p in matrix) {
159             this.board[matrix[p][0]][matrix[p][1]] = color;
160         }
161     }
162     this.drawBoard();
163     this.soundSource = {
164         'end': 'sounds/GameEndChimes.wav',
165         'setStone': 'sounds/Pieces_SinglePlaced.wav',
166         'dropStone': 'sounds/PiecesFillPocket.wav',
167         'positive': 'sounds/PositiveSound.wav',
168         'settingbtn': 'sounds/SettingsButton.wav',
169         'settingck': 'sounds/SettingsButtonCheck.wav',
170         'settingon': 'sounds/SettingsAppearWoodSlide.wav',
171         'dida': 'sounds/ClockTicking_Loop.wav',
172     };
173
174     this.sounds = {};
175
176     this.disable('.'+this.winMessage);
177     this.enable('.'+this.playButton);
178
179 }
180
181 Go.start = function(){
182     for (var i=0; i<this.bounder; i++){
183         for (var j=0; j<this.bounder; j++){
184             this.board[i][j] = 'board';
185         }
186     }
187     this.player['black'] = new player('black');
188     this.player['white'] = new player('white');
189     this.current = this.player['white'];
190     this.isStart = true;
191     this.isStop = false;
192     this.isPass = false;
193     this.isSetting =false;
194     this.isRestart = false;
195     this.isExit = false;
196     this.isEndMsg = true;
197     this.drawBoard();
198     this.drawMessage();
199     this.disable('.'+this.playButton);
200     this.disable('.'+this.winMessage);
201     this.disable('.'+this.settingPanel);
202     this.disable('.'+this.helpPanel);
203     this.playSound('settingbtn');
204     // this.startTimer();
205
206     $('.setting_restart img').attr('src', this.texture['uncheck'])
207         .removeClass('setting_restart_checked')
208         .addClass('setting_restart_check');
209 }
210
211 Go.getSoundSource = function(snd) {
212     var ret = this.sounds[snd];
213     if (typeof ret == 'undefined') {
214         var src = this.soundSource[snd];
215         if (snd == 'dida') {
216             ret = new gamesound(src);
217         } else {
218             ret = new Audio(src);
219         }
220         this.sounds[snd] = ret;
221     }
222     return ret;
223 }
224
225 Go.playSound = function(snd){
226     if (this.isSound) {
227         var audio = this.getSoundSource(snd);
228         if (audio.paused == false) {
229             audio.pause();
230             audio.currentTime = 0;
231         }
232         audio.play();
233     }
234 }
235
236 Go.stop = function(){
237     this.isStart = false;
238     this.isStop = true;
239     this.stopTimer();
240     var blackScore = this.player['black'].getScore();
241     var whiteScore = this.player['white'].getScore();
242     this.initWinMessage();
243     if (blackScore > whiteScore){
244         $('#win_player').html(' '+getMessage('one', 'One'));
245         $('#win_result').html(getMessage('win', 'Wins'));
246     } else if (blackScore < whiteScore) {
247         $('#win_player').html(' '+getMessage('two', 'Two'));
248         $('#win_result').html(getMessage('win', 'Wins'));
249     } else {
250         $('#win_player').html('');
251         $('#win_result').html(getMessage('draw', 'Draw'));
252     }
253     if (this.isEndMsg) {
254         this.playSound('end');
255         this.enable('.'+this.winMessage);
256         this.isEndMsg = false;
257     }
258 }
259
260 Go.initWinMessage = function() {
261     if (!this.hasWinMessage) {
262         var winmsg = $('.'+this.winMessage);
263         winmsg.html('<a onClick="javascript:Go.disable('+"'.win_panel');"+'" class="win_exit">X</a> <div class="win_arrow" align="center"> <span style="font-size:55pt;"><span name="player"></span><span id="win_player"></span></span><br> <span style="font-size:70pt;" id="win_result"></span> <img class="win_arrow_img" src="images/GO_WinArrow_012012_a.png" /> </div> <a onClick="javascript:Go.start();" class="replay"> </a>');
264         $('.replay').html(getMessage('newGame', 'New Game'));
265         $('span[name="player"]').html(getMessage('player', 'Player'));
266         this.hasWinMessage = true;
267     }
268
269 }
270
271 Go.exit = function(){
272     if (this.isExit) {
273         window.close();
274     }
275 }
276
277 Go.restart = function(){
278     if (this.isRestart){
279         if (this.isEndMsg) {
280             this.stop();
281         } else {
282             this.start();
283         }
284     }
285 }
286
287 Go.startTimer = function(){
288     if (this.isTimer && this.isStart) {
289         this.timer = setTimeout('Go.startTimer()',1000);
290         this.current.timeDida();
291         this.playSound('dida');
292         if (this.current.restTime <= 0) {
293             this.stop();
294         } else if (this.current.restTime == 5) {
295             this.playSound('positive');
296         }
297     }
298 }
299
300 Go.stopTimer = function(){
301     if (this.isTimer) {
302         clearTimeout(this.timer);
303         // this.sounds['dida'].pause();
304     }
305 }
306
307 Go.disable = function(which) {
308     $(which).addClass('display_none');
309 }
310
311 Go.enable = function(which) {
312     $(which).removeClass('display_none');
313 }
314
315 Go.toggleSetting = function(){
316     if ($('.'+this.winMessage).hasClass('display_none')) {
317         if (this.isSetting){
318             this.exitSetting();
319         } else {
320             this.showSetting();
321         }
322         this.playSound('settingbtn');
323     }
324 }
325
326 Go.initSettingPanel = function() {
327     if (!this.hasSettingPanel) {
328         var panel = $('.setting_panel');
329         panel.html('<a onClick="javascript:Go.toggleHelp();" class="setting_help">?</a> <a onClick="javascript:Go.toggleSetting();" class="setting_exit">X</a> <div id="licensebtnl" style="top: 490px; left: 405px;"> i </div> <div class="setting_arrow" align="center"> <span></span> <img class="setting_arrow_img" src="images/GO_SettingsArrow_010612_a.png" /> </div> <div class="setting_sound"> <span></span> <a onClick="javascript:Go.toggleSound();"><img class="setting_sound_check" src="images/GO_Checkbox_010612_a.png" /></a> </div> <div class="setting_timer"> <span></span> <a onClick="javascript:Go.toggleTimer();"><img class="setting_timer_check" src="images/GO_Checkbox_010612_a.png" /></a> </div> <div class="setting_restart"> <span></span> <a onClick="javascript:Go.toggleRestart();"><img class="setting_restart_check" src="images/GO_Checkbox_010612_a.png" /></a> </div> <div class="setting_quit"> <span class="setting_quit_text"></span> <a onClick="javascript:Go.toggleQuit();"><img class="setting_quit_check" src="images/GO_Checkbox_010612_a.png" /></a> </div> <a onClick="javascript:Go.toggleSetting();" class="setting_resume setting_resume_inactive" align="center"> </a>');
330         $('.setting_arrow span').html(getMessage('settings', 'Settings'));
331         $('.setting_sound span').html(getMessage('sound_setting', 'Sound FX....'));
332         $('.setting_timer span').html(getMessage('timer_setting', 'Timer...........'));
333         $('.setting_restart span').html(getMessage('restart', 'Restart'));
334         $('.setting_quit span').html(getMessage('quit', 'Quit'));
335         $('.setting_resume').html(getMessage('resume', 'Submit'));
336         $('#licensebtnl').click(function(){
337             Go.showLicense("license", "theworld");
338         });
339
340         this.hasSettingPanel = true;
341     }
342 }
343
344 Go.showSetting = function(){
345     this.initSettingPanel();
346     this.enable('.setting_panel');
347     setTimeout("$('.setting_panel').addClass('setting_panel_in')", 100);
348     this.isSetting = true;
349     this.stopTimer();
350     this.playSound('settingon');
351 }
352
353 Go.exitSetting = function(){
354     this.disable('.setting_panel');
355     $('.'+this.helpPanel).addClass('display_none');
356     $('.setting_panel').removeClass('setting_panel_in');
357     this.isSetting = false;
358     this.exit();
359     this.restart();
360     this.startTimer();
361 }
362
363 Go.toggleSound = function(){
364     var img = $('.setting_sound img');
365     if (this.isSound) {
366         img.attr('src', this.texture['uncheck']);
367         img.removeClass('setting_sound_checked');
368         img.addClass('setting_sound_check');
369         this.isSound = false;
370     } else {
371         img.attr('src', this.texture['checked']);
372         img.addClass('setting_sound_checked');
373         img.removeClass('setting_sound_check');
374         this.isSound = true;
375     }
376     this.playSound('settingck');
377 }
378
379 Go.toggleTimer = function(){
380     var img = $('.setting_timer img');
381     if (this.isTimer) {
382         img.attr('src', this.texture['uncheck']);
383         img.removeClass('setting_timer_checked');
384         img.addClass('setting_timer_check');
385         this.isTimer = false;
386     } else {
387         img.attr('src', this.texture['checked']);
388         img.addClass('setting_timer_checked');
389         img.removeClass('setting_timer_check');
390         this.isTimer = true;
391     }
392     this.playSound('settingck');
393 }
394
395 Go.toggleRestart = function(){
396     if (this.isStart || this.isStop) {
397         var conflict = false;
398         var img = $('.setting_restart img');
399         if (this.isRestart) {
400             img.attr('src', this.texture['uncheck']);
401             img.removeClass('setting_restart_checked');
402             img.addClass('setting_restart_check');
403             this.isRestart = false;
404         } else {
405             img.attr('src', this.texture['checked']);
406             img.addClass('setting_restart_checked');
407             img.removeClass('setting_restart_check');
408             this.isRestart = true;
409             if (this.isExit)
410                 conflict = true;
411         }
412         if (conflict) {
413             this.toggleQuit();
414         } else {
415             this.playSound('settingck');
416         }
417     }
418 }
419
420 Go.toggleQuit = function(){
421     var img = $('.setting_quit img');
422     var conflict = false;
423     if (this.isExit) {
424         img.attr('src', this.texture['uncheck']);
425         img.removeClass('setting_quit_checked');
426         img.addClass('setting_quit_check');
427         this.isExit = false;
428     } else {
429         img.attr('src', this.texture['checked']);
430         img.addClass('setting_quit_checked');
431         img.removeClass('setting_quit_check');
432         this.isExit = true;
433         if (this.isRestart)
434             conflict = true;
435     }
436     if (conflict) {
437         this.toggleRestart();
438     } else {
439         this.playSound('settingck');
440     }
441 }
442
443 Go.toggleHelp = function() {
444     var help = $('.'+this.helpPanel);
445     if (!this.hasHelp) {
446         help.html('<a onClick="javascript:Go.toggleHelp();" class="help_exit text_shadow">X</a> <div class="help_title text_shadow" ></div> <div class="help_text" > &nbsp;&nbsp;&nbsp;&nbsp;Take turns placing a stone on a vacant intersections (points) of the grid on a Go board. Black moves first. Once placed, a stone may not be moved, and can be removed only if captured. If a player believes he has no useful moves, he may skip his move (pass).<br> &nbsp;&nbsp;&nbsp;&nbsp;Vertically and horizontally adjacent stones of the same color form a chain (also called a string, or group) that shares liberties (adjacent, empty spaces) in common. These chains cannot be divided, and in effect becomes a single larger stone. Chains may be expanded by placing additional stones on adjacent points, and can be connected by placing a stone on a points adjacent to two or more chains of the same color.<br> &nbsp;&nbsp;&nbsp;&nbsp;A chain of stones must have at least one liberty to remain on the board. When a chain is surrounded by opposing stones so that it has no liberties, it is captured and removed from the board.<br> &nbsp;&nbsp;&nbsp;&nbsp;The game ends when both players have passed (clicked Skip) consecutively. The player who scores more points (the number of empty points, or intersections, surrounded by their pieces, plus the number of stones they'+"'" + 've captured) wins.<br> &nbsp;&nbsp;&nbsp;&nbsp;For more information on how to play Go, see the Wikipedia article on the game: <span><a style="opacity: 0.6; color: #0000FF" href="http://en.wikipedia.org/wiki/Go_(game)">http://en.wikipedia.org/wiki/Go_(game)</a></span>. </div>');
447         $('.help_title').html(getMessage('rules', 'Rules'));
448         var help_text = getMessage('help');
449         if (help_text.length > 0) {
450             $('.help_text').html(help_text);
451         }
452         this.hasHelp = true;
453     }
454     if (help.hasClass('display_none')) {
455         help.removeClass('display_none');
456     } else {
457         help.addClass('display_none');
458     }
459     //$('.'+this.helpPanel).toggleClass('display_none');
460 }
461
462 Go.drawBoard = function(){
463     var str = '';
464     var style=['margin:1px 0px 9px 0px;','margin:0px 10px 9px 0px;','margin:0px 9px 10px 0px;'];
465     for (var i=0; i<this.bounder; i++){
466         var margin=style[2];
467         if (i<6) margin = style[0];
468         str += '<div style="width:595px;height:36px;'+margin+'">';
469         for (var j=0; j<this.bounder; j++){
470             margin = style[2];
471             if (j<6) margin = style[1];
472             if (i>8) margin += 'position:relative;top:-5px;';
473             str += '<span style="float:left;width:36px;height:36px;'+margin
474                 +'"><a onClick="javascript:Go.click('+i+','+j+');" class="img_style" ><img src="'
475                 +this.texture[this.board[i][j]]+'" id="a'+i+j+'" class="board_img" /></a></span>';
476         }
477         str += '</div>';
478     }
479     $('.'+this.boardview).html(str);
480 }
481
482 Go.click = function(i, j){
483     if (this.board[i][j]==='board' && !this.isSetting && this.isStart) {
484         var revColor = (this.current.color=='black'?'white':'black');
485         var p = this.player[revColor];
486
487         this.board[i][j] = this.current.color;
488         var takes = this.getTake([i, j]);
489         if (takes.length == 1 && p.takes.length == 1
490             && p.takes[0][0] == i && p.takes[0][1] == j
491             && takes[0][0] == p.place[0] && takes[0][1] == p.place[1]) {
492             //Can't do mirror go
493             this.board[i][j] = 'board';
494             return;
495         }
496         for (var n in takes) {
497             this.board[takes[n][0]][takes[n][1]] = 'board';
498             p.dropStone();
499             p.score--;
500         }
501         if (takes.length == 0 && this.isContained(i, j, this.current.color)) {
502             this.board[i][j] = 'board';
503         } else {
504             var status = {'color':this.current.color,};
505             this.playSound('setStone');
506             if (takes.length > 0)
507                 this.playSound('dropStone');
508             status.setPlace = [i, j];
509             status.place = this.place;
510             this.place = [i, j];
511             this.current.score++;
512             status.userPlace = this.current.place;
513             this.current.place = this.place;
514             this.current.takes = takes;
515             status.takes = takes;
516             this.current.pickStone();
517             status.isPass = this.isPass;
518             this.isPass = false;
519
520             // Get Liberty
521             var liberty = this.getLiberty();
522             status.liberty = {};
523             status.liberty['black'] = this.player['black'].liberty;
524             status.liberty['white'] = this.player['white'].liberty;
525             this.player['black'].liberty = liberty['black'];
526             this.player['white'].liberty = liberty['white'];
527
528             status.restTime = {};
529             status.restTime['black'] = this.player['black'].restTime;
530             status.restTime['white'] = this.player['white'].restTime;
531             this.manual.push(status);
532             this.drawBoard();
533             this.drawMessage();
534         }
535     }
536 }
537
538 Go.undue = function(color_) {
539     if (!this.isSetting && this.isStart && color_ != this.current.color) {
540         var status = this.manual.pop();
541         if (status) {
542             var color = status.color;
543             var revColor = (color == 'black'?'white':'black');
544             var player = this.player[color];
545             if (status.setPlace.length > 0) {
546                 this.place = status.place;
547                 player.dropStone();
548                 player.score--;
549                 this.board[status.setPlace[0]][status.setPlace[1]] = 'board';
550                 for (var p in status.takes) {
551                     var take = status.takes[p];
552                     this.player[revColor].pickStone();
553                     this.board[take[0]][take[1]] = revColor;
554                     this.player[revColor].score++;
555                 }
556                 if (status.liberty) {
557                     var liberty = status.liberty;
558                     this.player['black'].liberty = liberty['black'];
559                     this.player['white'].liberty = liberty['white'];
560                 } else {
561                     this.player['black'].liberty = [];
562                     this.player['white'].liberty = [];
563                 }
564                 player.place = status.userPlace;
565                 this.drawBoard();
566             }
567             this.isPass = status.isPass;
568             // Reset the timer
569             // this.player['black'].restTime = status.restTime['black'];
570             // this.player['white'].restTime = status.restTime['white'];
571             this.drawMessage();
572         }
573     }
574 }
575
576 Go.getTake = function(place_) {
577     var p = place_ || this.place;
578     var checkColor = (this.current.color=='black'?'white':'black');
579     var takes = [];
580     for (var d in this.directs) {
581         var i = parseInt(p[0])+parseInt(this.directs[d][0]);
582         var j = parseInt(p[1])+parseInt(this.directs[d][1]);
583         if (i>=0 && j>= 0 && i<this.bounder && j<this.bounder
584             && this.board[i][j] === checkColor) {
585             var t = [];
586             if (this.isContained(i, j, checkColor, t)) {
587                 for (var n in t){
588                     if (!this.isContain(t[n], takes)) {
589                         takes.push(t[n]);
590                     }
591                 }
592             }
593         }
594     }
595     //console.log(takes);
596     return takes;
597 }
598
599 Go.isContained = function(i_, j_, color_, contains_, except_) {
600     var color = color_ || (this.current.color == 'black'?'white':'black');
601     var except = except_ || [];
602     var contains = contains_ || [];
603     var ret = true;
604     except.push([parseInt(i_),parseInt(j_)]);
605
606     for (var d in this.directs) {
607         if (!ret)
608             break;
609         var i = parseInt(i_)+parseInt(this.directs[d][0]);
610         var j = parseInt(j_)+parseInt(this.directs[d][1]);
611         if ( i>=0 && j>= 0 && i<this.bounder && j<this.bounder
612             && !this.isContain([i,j], except)) {
613             if (this.board[i][j] == 'board') {
614                 ret = false;
615             } else if (this.board[i][j] == color) {
616                 if (!this.isContained(i, j, color, contains, except)) {
617                     ret = false;
618                 }
619             }
620         }
621     }
622     if (ret)
623         contains.push([i_, j_]);
624     return ret;
625 }
626
627 Go.getLiberty = function(){
628     var except = [];
629     var contain = {
630         'black':[],
631         'white':[],
632     };
633     for (var i=0; i<this.bounder; i++){
634         for (var j=0; j<this.bounder; j++){
635             if (this.board[i][j] == 'board' && !this.isContain([i,j], except)) {
636                 var except_ = [];
637                 var liberty = this.countLiberty(i,j,except_);
638                 if (!liberty.hasOwnProperty('none')) {
639                     var color = 'none';
640                     if (liberty.hasOwnProperty('black')) {
641                         color = 'black';
642                     } else if (liberty.hasOwnProperty('white')) {
643                         color = 'white';
644                     }
645                     if (color != 'none') {
646                         var needpush = liberty[color];
647                         for (var n in needpush){
648                             if (!this.isContain(needpush[n], contain[color])) {
649                                 contain[color].push(needpush[n]);
650                             }
651                         }
652                     }
653                 }
654                 for (var n in except_) {
655                     if (!this.isContain(except_[n], except)) {
656                         except.push(except_[n]);
657                     }
658                 }
659             }
660         }
661     }
662
663     return contain;
664 }
665
666 Go.countLiberty = function(i_,j_,except){
667     var ret = {};
668     except.push([i_,j_]);
669     for (var d in this.directs) {
670         if (ret.hasOwnProperty('none'))
671             break;
672         var i = parseInt(i_)+parseInt(this.directs[d][0]);
673         var j = parseInt(j_)+parseInt(this.directs[d][1]);
674         if (i>=0 && j>= 0 && i<this.bounder && j<this.bounder && !this.isContain([i,j], except)) {
675             if (this.board[i][j] == 'board') {
676                 var liberty = this.countLiberty(i,j,except);
677                 if (liberty.hasOwnProperty('none')) {
678                     ret['none'] = [];
679                     break;
680                 } else if (liberty.hasOwnProperty('black')){
681                     if (ret.hasOwnProperty('white')) {
682                         ret['none'] = [];
683                         break;
684                     } else {
685                         if (!ret.hasOwnProperty('black'))
686                             ret['black'] = [];
687                         for (var n in liberty['black']){
688                             if (!this.isContain(liberty['black'][n], ret['black'])) {
689                                 ret['black'].push(liberty['black'][n]);
690                             }
691                         }
692                     }
693                 } else if (liberty.hasOwnProperty('white')) {
694                     if (ret.hasOwnProperty('black')) {
695                         ret['none'] = [];
696                         break;
697                     } else {
698                         if (!ret.hasOwnProperty('white'))
699                             ret['white'] = [];
700                         for (var n in liberty['white']){
701                             if (!this.isContain(liberty['white'][n], ret['white'])) {
702                                 ret['white'].push(liberty['white'][n]);
703                             }
704                         }
705                     }
706                 } else if (liberty.hasOwnProperty('neutral')) {
707                     if (!ret.hasOwnProperty('neutral'))
708                         ret['neutral'] = [];
709                     for (var n in liberty['neutral']){
710                         if (!this.isContain(liberty['neutral'][n], ret['neutral'])) {
711                             ret['neutral'].push(liberty['neutral'][n]);
712                         }
713                     }
714                 }
715             } else if (this.board[i][j] == 'black') {
716                 if (ret.hasOwnProperty('white')) {
717                     ret['none'] = [];
718                     break;
719                 } else if (!ret.hasOwnProperty('black')) {
720                     ret['black'] = [];
721                 }
722             } else if (this.board[i][j] == 'white') {
723                 if (ret.hasOwnProperty('black')) {
724                     ret['none'] = [];
725                     break;
726                 } else if (!ret.hasOwnProperty('white')) {
727                     ret['white'] = [];
728                 }
729             }
730         }
731     }
732     if (!ret.hasOwnProperty('none')) {
733         if (ret.hasOwnProperty('black')) {
734             if (!this.isContain([i_,j_], ret['black']))
735                 ret['black'].push([i_,j_]);
736             if (ret.hasOwnProperty('neutral')){
737                 for (var p = ret['neutral'].shift(); typeof p != 'undefined'; p = ret['neutral'].shift()) {
738                     if (!this.isContain(p, ret['black'])) {
739                         ret['black'].push(p);
740                     }
741                 }
742             }
743         } else if (ret.hasOwnProperty('white')) {
744             if (!this.isContain([i_,j_], ret['white']))
745                 ret['white'].push([i_,j_]);
746             if (ret.hasOwnProperty('neutral')){
747                 for (var p = ret['neutral'].shift(); typeof p != 'undefined'; p = ret['neutral'].shift()) {
748                     if (!this.isContain(p, ret['white'])) {
749                         ret['white'].push(p);
750                     }
751                 }
752             }
753         } else {
754             if (!ret.hasOwnProperty('neutral'))
755                 ret['neutral'] = [];
756             if (!this.isContain([i_,j_], ret['neutral']))
757                 ret['neutral'].push([i_,j_]);
758         }
759     }
760     return ret;
761 }
762
763 Go.isContain = function(place, _array) {
764     var heat = _array || [];
765     for (var i in heat){
766         if (heat[i][0] == place[0] && heat[i][1] == place[1]) {
767             return true;
768         }
769     }
770     return false;
771 }
772
773 Go.drawMessage = function(){
774     this.current.stop();
775     this.current = this.player[(this.current.color=='black'?'white':'black')];
776     this.current.start();
777 }
778
779 Go.skip = function(color_){
780     var color = color_ || this.current.color;
781     if (this.current.color == color && !this.isSetting && this.isStart) {
782         this.playSound('settingbtn');
783         if (this.isPass) {
784             this.stop();
785         } else {
786             var status = {'color': this.current.color,
787                           'setPlace': [],
788                           'isPass': false,};
789             status.restTime = {};
790             status.restTime['black'] = this.player['black'].restTime;
791             status.restTime['white'] = this.player['white'].restTime;
792             this.manual.push(status);
793             this.drawMessage();
794             this.isPass = true;
795         }
796     }
797 }
798
799 function player(color_) {
800     this.color = color_;
801     var side = (color_ == 'black'?'left':'right');
802     this.restTime = 20*60;
803     this.score = 0;
804     this.place = [-1,-1];
805     this.stoneNum = Math.floor(Go.bounder*Go.bounder);
806     this.takes = [];
807     this.liberty = [];
808     this.resource = {
809         'pit':side+'_pit',
810         'arrow':side+'_arrow',
811         'timer':side+'_timer',
812         'score':side+'_score',
813         'stone':Go.texture[this.color],
814         'stone1':Go.texture[this.color+'1'],
815         'stone2':Go.texture[this.color+'2'],
816     };
817
818     var str = '';
819     $('.'+this.resource['pit']).html(str);
820     for (var i=0; i<this.stoneNum; i++){
821         var x = Math.floor(Math.random()*76)+20;
822         var y = Math.floor(Math.random()*296)+20;
823         var ext = Math.floor(Math.random()*16);
824         if (ext != 1 && ext != 2) ext = '';
825         str += '<img class="stone_in_pit" id="'+this.color+'stone'+i+'" style="top:'+y+'px;left:'+x+'px;" src="'+this.resource['stone'+ext]+'" />';
826     }
827     $('.'+this.resource['pit']).html(str);
828
829     $('.'+this.resource['timer']+' span').html('20:00');
830
831     this.currentStone = this.stoneNum-1;
832
833     this.dropStone = function() {
834         var x = Math.floor(Math.random()*76)+20;
835         var y = Math.floor(Math.random()*296)+20;
836         // var id = Math.floor(Math.random()*this.stoneNum);
837         var id = this.currentStone++;
838         var ext = Math.floor(Math.random()*16);
839         if (ext != 1 && ext != 2) ext = '';
840         $('#'+this.color+'stone'+id).attr('style', 'top:'+y+'px;left:'+x+'px;').attr('src', this.resource['stone'+ext]).removeClass('display_none');
841     }
842
843     this.pickStone = function(){
844         // var id = Math.floor(Math.random()*this.stoneNum);
845         var id = this.currentStone--;
846         $('#'+this.color+'stone'+id).addClass('display_none');
847     }
848
849     this.start = function(){
850         $('.'+this.resource['arrow']+' img').attr('src', this.texture['hi_arrow']);
851         this.updateScore();
852         this.updateTimer();
853         Go.startTimer();
854         //this.pickStone();
855     }
856
857     this.stop = function(){
858         $('.'+this.resource['arrow']+' img').attr('src', this.texture['arrow']);
859         this.updateScore();
860         Go.stopTimer();
861         this.updateTimer();
862     }
863
864     this.timeDida = function(){
865         this.restTime--;
866         this.updateTimer();
867     }
868
869     this.updateTimer = function() {
870         if (this.restTime >= 0){
871             var s = this.restTime%60;
872             var m = Math.floor(this.restTime/60);
873             var s1 = s%10;
874             var s2 = Math.floor(s/10);
875             var m1 = m%10;
876             var m2 = Math.floor(m/10);
877             var t = ''+m2+m1+':'+s2+s1;
878             //console.log(this.color+'['+t+']');
879             $('.'+this.resource['timer']+' span').html(t);
880         }
881     }
882
883     this.getScore = function() {
884                 if(this.score == 1){
885                         return 1;
886                 }
887                 else{
888                         return (this.score+this.liberty.length);
889                 }
890     }
891
892     this.updateScore = function(){
893         var str = '';
894         var s = this.getScore();
895         for (var i=0; i<4; i++){
896             str = s%10 + str;
897             s = Math.floor(s/10);
898         }
899         $('#'+this.resource['score']).html(str);
900     }
901 }
902
903 player.prototype.texture = {
904     'arrow':'images/GO_PlayerArrow_010612_a.png',
905     'hi_arrow':'images/GO_PlayerArrow_012012_b.png',
906 }
907
908 Go.showLicense = function(id, hpageid) {
909     var lbtn = document.getElementById(id+"btnl");
910
911     var lpage = document.getElementById(id+"page");
912     var hpage = document.getElementById(hpageid);
913     var ltext;
914     var lscroll;
915     var timer;
916
917     if (!this.hasLicense) {
918         $('#licensepage').html('<div id="licensetext"><div id="licensescroll"></div></div> <div id="licensebtnq" class="licensebtn">Back</div>');
919         lscroll = document.getElementById(id+"scroll");
920         var request = new XMLHttpRequest();
921         request.open("GET", "README.txt", false);
922         request.onload = function(e) {
923             var text = this.responseText;
924             text = text.replace("<","&lt;");
925             text = text.replace(">","&gt;");
926             var lines = text.split("\n");
927             lines[0] = "<br><br>"+lines[0];
928             for(var i in lines)
929             {
930                 if(lines[i].match(/--------------------/))
931                 {
932                     lines[i] = "";
933                 }
934                 else
935                 {
936                     lines[i] += "<br>";
937                 }
938             }
939             lscroll.innerHTML = lines.join("\n");
940         }
941         request.send();
942         this.hasLicense = true;
943     }
944
945     var btnq = document.getElementById(id+"btnq");
946     lscroll = document.getElementById(id+"scroll");
947     ltext = document.getElementById(id+"text");
948     /* initialize scroll rate */
949     var dY = 2;
950     var t0 = 0;
951     var delay = 1000;
952
953     /* set the scroller to the top position */
954     lscroll.style.top = "0px";
955
956     /* display the license page, hide its parent */
957     hpage.style.display="none";
958     lpage.style.display="block";
959
960     /* calculate the scroll length when the window is shown */
961     var maxY = lscroll.clientHeight - ltext.clientHeight;
962
963     /* start the autoscroll interval */
964     timer = setInterval(function() {
965         /* get the actual interval, in case performance slows us down */
966         var t1 = (new Date()).getTime();
967         var dT = (t0 == 0)?20:(t1-t0);
968         t0 = t1;
969
970         /* delay specific number of milliseconds */
971         delay -= dT;
972         if(delay > 0)
973             return;
974
975         /* calculate the new top position using dY and dT */
976         var newY = Math.abs(parseInt(lscroll.style.top)) + ((dT/40)*dY);
977         if(newY > 0)
978             lscroll.style.top = (-1 * newY) + "px";
979         else
980             lscroll.style.top = "0px";
981
982         /* if the lscroll has hit the limit, delay and swing */
983         /* the other way */
984         if(newY >= maxY)
985         {
986             delay = 5000;
987             dY = -20;
988         }
989         else if(newY <= 0)
990         {
991             delay = 5000;
992             dY = 2;
993         }
994     }, 40);
995
996     btnq.onclick = function() {
997         hpage.style.display="block";
998         lpage.style.display="none";
999         clearInterval(timer);
1000     }
1001 }
1002
1003 var messages;
1004
1005 function getMessage(key, alter) {
1006     var ret = alter || '';
1007     if (locale && locale == 'en' && ret.length>0) {
1008         return ret;
1009     }
1010     if (window.chrome && window.chrome.i18n && window.chrome.i18n.getMessage) {
1011         ret = chrome.i18n.getMessage(key);
1012     } else {
1013         if (typeof messages == 'undefined') {
1014             try {
1015                 var request = new XMLHttpRequest();
1016                 request.open("GET", "_locales/en/messages.json", false);
1017                 request.send();
1018                 var res = request.responseText;
1019                 messages = window.eval(res);
1020             } catch (err) {
1021                 return ret;
1022             }
1023         }
1024         if (messages && (messages.hasOwnProperty(key)) && (messages[key].hasOwnProperty('message'))) {
1025             ret = messages[key].message;
1026         }
1027     }
1028     return ret;
1029 }
1030
1031 var locale;
1032
1033 window.onload = function(){
1034     locale = getMessage('locale', 'en');
1035     if (locale != 'en') {
1036         var head  = $('head').q;
1037         var link  = document.createElement('link');
1038         link.rel  = 'stylesheet';
1039         link.type = 'text/css';
1040         link.href = 'css/i18n.css';
1041         head.appendChild(link);
1042     }
1043
1044     $('title').html(getMessage('name', 'Go'));
1045     $('#playerone').html(getMessage('player', 'Player')+' '+getMessage('one', 'One'));
1046     $('#playertwo').html(getMessage('player', 'Player')+' '+getMessage('two', 'Two'));
1047     $('.left_arrow span[name="score"]').html(getMessage('score', 'Score'));
1048     $('.right_arrow span[name="score"]').html(getMessage('score', 'Score'));
1049     $('.left_skip').html(getMessage('skip', 'Skip'));
1050     $('.right_skip').html(getMessage('skip', 'Skip'));
1051     $('.play_button_text').html(getMessage('play', 'Play'));
1052
1053     //Pass game, continue pass cause the end
1054     $('.left_skip').click(function(){
1055         Go.skip('black');
1056     });
1057
1058     $('.right_skip').click(function(){
1059         Go.skip('white');
1060     });
1061
1062     Go.init();
1063 }
1064
1065