elo-worldle/main.min.js

7 lines
16 KiB
JavaScript
Raw Permalink Normal View History

2023-04-01 23:11:32 -04:00
import{Chess,Ox88,DEFAULT_POSITION,SQUARES,rank,file,WHITE,BLACK,KING}from"./chess.min.js";function with_move(board,move){let new_board=new Chess(board.fen());new_board.move(move);return new_board}function shuffle(array){let currentIndex=array.length,randomIndex;while(currentIndex!=0){randomIndex=Math.floor(Math.random()*currentIndex);currentIndex--;[array[currentIndex],array[randomIndex]]=[array[randomIndex],array[currentIndex]]}return array}function min_move_by(board,score){let best_score=Infinity;let best_move="";let moves=board.moves();shuffle(moves);for(const move of moves){try{let new_board=with_move(board,move);let new_score=score(new_board);if(new_score<best_score){console.log("New best (or equal): ",new_score,move);best_score=new_score;best_move=move}}catch(e){console.error(e);continue}}return best_move}const random_move=board=>{const moves=board.moves();const move=moves[Math.floor(Math.random()*moves.length)];return move};function make_lexo(m){let{rank:src_row,file:src_col}=rank_and_file(m.from);let{rank:dst_row,file:dst_col}=rank_and_file(m.to);let promote_to=m.promotion;return[src_row,src_col,dst_row,dst_col,promote_to]}function lexo_sort_moves(a,b){let al=make_lexo(a);let bl=make_lexo(a);for(const i in al){if(al[i]<bl[i]){return-1}else if(al[i]>bl[i]){return 1}}return 0}const first_move=board=>{const moves=board.moves({verbose:true}).sort(lexo_sort_moves);return moves[0].san};const alphabetical=board=>{const moves=board.moves();moves.sort();return moves[0]};const equalizer_state_default={piece_moves:{p:0,b:0,n:0,r:0,q:0,k:0},square_visits:{a8:0,b8:0,c8:0,d8:0,e8:0,f8:0,g8:0,h8:0,a7:0,b7:0,c7:0,d7:0,e7:0,f7:0,g7:0,h7:0,a6:0,b6:0,c6:0,d6:0,e6:0,f6:0,g6:0,h6:0,a5:0,b5:0,c5:0,d5:0,e5:0,f5:0,g5:0,h5:0,a4:0,b4:0,c4:0,d4:0,e4:0,f4:0,g4:0,h4:0,a3:0,b3:0,c3:0,d3:0,e3:0,f3:0,g3:0,h3:0,a2:0,b2:0,c2:0,d2:0,e2:0,f2:0,g2:0,h2:0,a1:0,b1:0,c1:0,d1:0,e1:0,f1:0,g1:0,h1:0}};var equalizer_state=equalizer_state_default;const equalizer=board=>{let best_move;let least_moved_found=Infinity;let least_visited_found=Infinity;let piece_moving="k";let square_visiting="a1";for(const move of board.moves({verbose:true})){if(equalizer_state.piece_moves[move.piece]<least_moved_found||equalizer_state.piece_moves[move.piece]==least_moved_found&&equalizer_state.square_visits[move.to]<least_visited_found){best_move=move;least_moved_found=equalizer_state.piece_moves[move.piece];least_visited_found=equalizer_state.square_visits[move.to];piece_moving=move.piece;square_visiting=move.to}}equalizer_state.piece_moves[piece_moving]+=1;equalizer_state.square_visits[square_visiting]+=1;return best_move.san};const min_oppt_move=board=>{let num_moves=b=>b.moves().length;return min_move_by(board,num_moves)};function num_pieces_on_own_color(b){let count=0;for(const square of SQUARES){let piece=b.get(square);if(typeof piece=="boolean"){continue}if(piece.color==b.squareColor(square)){count+=1}}return count}const same_color=board=>{return min_move_by(board,b=>64-num_pieces_on_own_color(b))};const opposite_color=board=>{return min_move_by(board,num_pieces_on_own_color)};function rank_and_file(s){return{rank:rank(Ox88[s]),file:file(Ox88[s])}}function chebyshev_distance(a,b){let{rank:r1,file:f1}=rank_and_file(a);let{rank:r2,file:f2}=rank_and_file(b);return Math.max(Math.abs(r2-r1),Math.abs(f2-f1))}const START_BOARD=new Chess(DEFAULT_POSITION);function move_distance(piece){let rank=rank_and_file(piece.square).rank;let file=rank_and_file(piece.square).file;switch(piece.type){case"k":return chebyshev_distance(piece.square,find({color:HUMAN_COLOR,type:"k"},START_BOARD));case"p":return Math.abs(rank-6);case"r":return Math.abs(rank-7)+Math.min(Math.abs(file-7),Math.abs(file-0));case"n":return pieces_of_color(START_BOARD,HUMAN_COLOR).filter(p=>p.type=="k").map(p=>chebyshev_distance(piece.square,p.square)).reduce((a,b)=>Math.max(a,b));case"b":let is_black=START_BOARD.squareColor(piece.square)=="b";let dest_col=is_black?2:5;let dr=Math.abs(rank-7);let dc=Math.abs(file-dest_col);return Math.max(dr,dc);case"q":return Math.max(Math.abs(rank-7),Math.abs(file-3))}}function mini
#ew_${todays_player.name}
Win #${wins}
Guesses: ${num_guesses}
Moves: ${num_moves}
2023-04-01 23:37:30 -04:00
${history}`;stats.innerText=stats_text;let copy_stats=document.getElementById("copy-stats");copy_stats.style.display="block";copy_stats.addEventListener("click",_=>copy_stats_to_clipboard());let play_again=document.getElementById("play-again");play_again.style.display="block";play_again.addEventListener("click",_=>reset());console.log("PLAYER IS WIN")}var num_guesses=0;var num_moves=0;var history="";function append_players_to(n){for(const player of players){let child=document.createElement("div");child.classList.add("player");let child_name=document.createElement("h1");child_name.classList.add("player-name");child_name.innerText=player.name;let child_desc=document.createElement("p");child_desc.classList.add("player-desc");child_desc.innerText=player.description;let guess_button=document.createElement("button");guess_button.innerText="^ guess ^";guess_button.onclick=_=>{num_guesses++;history+="G";if(todays_player.name==player.name){show_win();child.classList.add("correct")}else{child.classList.add("wrong")}guess_button.onclick=()=>{}};child.appendChild(child_name);child.appendChild(child_desc);child.appendChild(guess_button);child_name.addEventListener("click",_=>child.classList.toggle("strikethrough"));n.appendChild(child)}}var wins=0;function wins_exclamation_marks(){let base_10_log_of_wins=Math.floor(Math.log10(wins));return base_10_log_of_wins>0?"!".repeat(base_10_log_of_wins):"."}var in_game_over=false;function reset(){let play_again=document.getElementById("play-again");play_again.style.display="none";play_again.onclick=_=>console.log("you can't play again again sorry :]");in_game_over=false;todays_player=get_todays_player();game=new Chess;board.fen=game.fen();board.turn="white";board.interactive=true;num_guesses=0;num_moves=0;history="";equalizer_state=equalizer_state_default;let players=document.getElementById("players");players.innerHTML="";append_players_to(players);let stats=document.getElementById("stats");stats.innerHTML="";stats.style.display="none";document.getElementById("copy-stats").style.display="none";document.getElementById("game-over").style.display="none"}window.addEventListener("DOMContentLoaded",()=>{document.getElementById("dummy-board").style.display="none";document.getElementById("players").classList.remove("much-tall");board.addEventListener("movestart",e=>{console.log(`Move started: ${e.detail.from}, ${e.detail.piece.color} ${e.detail.piece.pieceType}`);e.detail.setTargets(game.moves({square:e.detail.from,verbose:true}).map(m=>m.to));if(game.isGameOver()){show_game_over()}});board.addEventListener("moveend",e=>{console.log(`Move ending: ${e.detail.from} -> ${e.detail.to}, ${e.detail.piece.color} ${e.detail.piece.pieceType}`);const move=game.move({from:e.detail.from,to:e.detail.to,promotion:"q"});if(move===null){e.preventDefault()}if(game.isGameOver()){show_game_over()}});board.addEventListener("movefinished",e=>{board.fen=game.fen();board.turn=game.turn()==="w"?"white":"black";board.interactive=game.turn()==="w";if(!board.interactive){let move=computer_move();if(!move){console.log("Didn't get a move from the computer (this is fine if the game is over)");return}console.log(`Computer move: ${move}`);game.move(move);board.fen=game.fen();board.turn="white";board.interactive=true}});document.getElementById("finish").addEventListener("click",_=>show_game_over());document.addEventListener("keypress",e=>{if(e.key=="r"&&in_game_over){reset()}else if(e.key=="c"&&in_game_over){copy_stats_to_clipboard()}});append_players_to(document.getElementById("players"))});