// Copyright 2005 Jim Radford <radford@blackbean.org> -*- c -*-
// Copyright 2006 David Caldwell <david@porkrind.org>
function sudoku(board_div){this.div={board:board_div};seed_game.prototype.init.call(this,"sudoku");this.init_keyboard_focus_auto_pause(this.div.board);this.create();}
sudoku.prototype=merge(new KeyboardFocusAutoPause(),new seed_game());sudoku.prototype.from_text=function(text){text=text.replace(/%[^\n]+\n/,"");if(!text.match(/^([\s.\d]{9}\n){9}$/))
return;var lines=text.replace(/[ .]/g,nbsp).split("\n");for(var r=0;r<9;r++)
for(var c=0;c<9;c++){this.cell[r][c].state=lines[r].charAt(c);this.cell[r][c].known=!!lines[r].charAt(c).match(/\d/);}}
sudoku.prototype.square=function(sr,sc){return Math.floor(sr/3)*3+Math.floor(sc/3);}
sudoku.prototype.map=function(type,i,callback){if(type=="col")for(var r=0;r<9;r++)callback(this.cell[r][i],r,i);else
if(type=="row")for(var c=0;c<9;c++)callback(this.cell[i][c],i,c);else
if(type=="square"){var sr=Math.floor(i/3)*3;var sc=i%3*3;for(var r=0;r<3;r++)for(var c=0;c<3;c++)callback(this.cell[sr+r][sc+c],sr+r,sc+c);}}
sudoku.prototype.is_complete=function()
{var axis=["row","col","square"];for(var a in axis){for(var i=0;i<9;i++){var digits=[];this.map(axis[a],i,function(cell){digits.push(cell.state);});if(digits.sort(function(a,b){return a-b}).join("")!="123456789")return NOT_COMPLETE;}}
return WON;}
sudoku.prototype.set_state=function(old){this.seed=old.seed;for(var r=0;r<9;r++)for(var c=0;c<9;c++){this.cell[r][c].state=old.cell[r][c].state;this.cell[r][c].known=old.cell[r][c].known;}
this.cursor.r=old.cursor.r
this.cursor.c=old.cursor.c
this.show_state();}
sudoku.prototype.get_state=function(){return{seed:this.seed,cursor:{r:this.cursor.r,c:this.cursor.c},cell:map(function(row){return map(function(cell){return{state:cell.state,known:cell.known};},row);},this.cell)};}
sudoku.prototype.show_state=function(){for(var r=0;r<this.cell.length;r++)
for(var c=0;c<this.cell[r].length;c++){this.cell[r][c].div.className=r==this.cursor.r&&c==this.cursor.c?"cursor":this.cell[r][c].known?"known":"unknown";this.cell[r][c].text.data=this.cell[r][c].state;}}
sudoku.prototype.create=function(){this.highlight=function(draw){this.cell[this.cursor.r][this.cursor.c].div.className=draw?"cursor":"unknown";}
var table=document.createElement("table");var tbody=document.createElement("tbody");table.cellSpacing=0;table.className="grid";var bw=table.style.borderWidth="3px";this.cell=[];for(var r=0;r<9;r++){var tr=document.createElement("tr");this.cell[r]=[];for(var c=0;c<9;c++){this.cell[r][c]={};var td=document.createElement("td");var div=document.createElement("div");this.cell[r][c].div=div;this.cell[r][c].erasure=0;div.className="unknown";td.style.borderWidth="1px";if(c%3==0)td.style.borderLeftWidth=bw;if(r%3==0)td.style.borderTopWidth=bw;if(c%3==2)td.style.borderRightWidth=bw;if(r%3==2)td.style.borderBottomWidth=bw;div.appendChild(this.cell[r][c].text=document.createTextNode(nbsp));div.onmousedown=(function(me,row,col){return function(){if(me.cell[row][col].state==nbsp)return;var oldup=window.onmouseup;for(var r=0;r<9;r++)for(var c=0;c<9;c++)
if(me.cell[r][c].state==me.cell[row][col].state){var highlight=function(cell,r,c){if(!me.cell[r][c].div.className.match(/similar/))
me.cell[r][c].div.className+=" similar";}
me.map("row",r,highlight);me.map("col",c,highlight);me.map("square",me.square(r,c),highlight);me.cell[r][c].div.className+=" same";}
document.onmouseup=function(){for(var r in me.cell)for(var c in me.cell[r])
if(me.cell[r][c].div.className.match(/same|similar/))
me.cell[r][c].div.className=me.cell[r][c].known?"known":"unknown";window.onmouseup=oldup;}
return false;}})(this,r,c);div.onclick=(function(me,r,c){return function(){if(me.cell[r][c].known)return;me.highlight(false);me.cursor.r=r;me.cursor.c=c;me.highlight(true);};})(this,r,c);td.appendChild(div);tr.appendChild(td);}
tbody.appendChild(tr);}
table.appendChild(tbody);if(this.div.board.firstChild)
this.div.board.removeChild(this.div.board.firstChild);this.div.board.appendChild(table);this.cursor={c:0,r:0};this.move=function(dr,dc,stop,change_orient){this.highlight(false);do{this.cursor.r=(this.cursor.r+dr+this.cell.length)%this.cell.length;this.cursor.c=(this.cursor.c+dc+this.cell[0].length)%this.cell[0].length;}while(this.cell[this.cursor.r][this.cursor.c].known);this.highlight(true);}
var me=this;this.set=function(c){if(me.cell[me.cursor.r][me.cursor.c].text.data!=nbsp&&me.cell[me.cursor.r][me.cursor.c].text.data!=c)
me.cell[me.cursor.r][me.cursor.c].erasure+=me.cell[me.cursor.r][me.cursor.c].text.className=="pencil"?1:2;me.cell[me.cursor.r][me.cursor.c].text.data=me.cell[me.cursor.r][me.cursor.c].state=c;}
this.register_key_events(function(event){if(event.key=="#"){for(var r in me.grid)
for(var c in me.grid[r])
if(me.grid[r][c]&&me.cell[r][c].text.data!=me.grid[r][c].solution){wrong.push({div:me.cell[r][c].div,name:me.cell[r][c].text.className});me.cell[r][c].text.className="wrong";}
var oldup=window.onkeydown;window.onkeyup=function(event){window.onkeyup=oldup;for(var w in wrong)
wrong[w].text.className=wrong[w].name;}}
if(event.key=="%")
for(var r in me.cell)
for(var c in me.cell[r])
me.cell[r][c].text.data=me.cell[r][c].solution;switch(event.key){case"up":me.move(-1,0,false,!event.shiftKey);return false;case"down":me.move(+1,0,false,!event.shiftKey);return false;case"left":me.move(0,-1,false,!event.shiftKey);return false;case"right":me.move(0,+1,false,!event.shiftKey);return false;case"return":print("Return!\n");return false;case"enter":print("Enter!\n");return false;case"tab":print("Tab!\n");return false;case"backspace":event.key=nbsp;break;case"space":event.key=nbsp;break;}
if(!event.key.match(/^\d$/)&&event.key!=nbsp||event.ctrlKey||event.altKey||event.metaKey)
return true;me.push_state();me.set(event.key);me.end_of_move();return false;});this.on_pause=function(){this.highlight(false);}
this.on_unpause=function(){this.highlight(true);}}
sudoku.prototype.new_game=function(seed){seed_game.prototype.new_game.call(this,seed);this.difficulty="easy";loadText(makeurl("sudoku.cgi",{seed:this.seed,difficulty:this.difficulty}),wrap(this,function(board,error){if(board==undefined){printf("Error loading sudoku board: %s\n",error);return;}
this.from_text(board);this.cursor={r:0,c:0};while(this.cell[this.cursor.r][this.cursor.c].known)
this.cursor.c++;this.show_state();this.start_stats();this.input_focus();}));}
var the_game;on_load(function(){the_game=new sudoku(document.getElementById("board"));the_game.new_game(URL.param.game);gotd.start=function(){the_game.new_game(game_of_the_day);return false;};});
