1import{b as O,_ as We,j as l}from"./client-B-Oz738J.js";import{T as De}from"./ToolPage-Dwy0IH4M.js";import{M as Le,s as Q,C as te,N as de}from"./ToolUi-CDNt51r_.js";import"./SeoHead-CTJ5a3SL.js";import"./CopyButton-DzWiNVYm.js";const F=15,q=7,we=7,B="",ye={A:[9,1],B:[2,3],C:[2,3],D:[4,2],E:[12,1],F:[2,4],G:[3,2],H:[2,4],I:[9,1],J:[1,8],K:[1,5],L:[4,1],M:[2,3],N:[6,1],O:[8,1],P:[2,3],Q:[1,10],R:[6,1],S:[4,1],T:[6,1],U:[4,1],V:[2,4],W:[2,4],X:[1,8],Y:[2,4],Z:[1,10]},Ae=2;function J(r){return r?ye[r][1]:0}function $e(){const r=[];for(const[a,[s]]of Object.entries(ye))for(let o=0;o<s;o++)r.push(a);for(let a=0;a<Ae;a++)r.push(B);return r}function ne(r){const a=r.slice();for(let s=a.length-1;s>0;s--){const o=Math.floor(Math.random()*(s+1));[a[s],a[o]]=[a[o],a[s]]}return a}function ee(r,a){const s=Math.min(a,r.length);return{drawn:r.slice(0,s),remaining:r.slice(s)}}function Se(r,a){const s=Math.abs(r-q),o=Math.abs(a-q);return s===o&&s===7?"QW":s===7&&o===3||o===7&&s===3?"QL":s===o&&s===6?"TW":s===o&&s>=1&&s<=5||s===0&&o===0?"DW":s===1&&o===4||s===4&&o===1||s===3&&o===6||s===6&&o===3?"TL":s===2&&o===5||s===5&&o===2||s===2&&o===0||s===0&&o===2||s===6&&o===0||s===0&&o===6?"DL":null}function Be(){return Array.from({length:F},()=>Array(F).fill(null))}function U(r,a){return r>=0&&r<F&&a>=0&&a<F}function Ie(r){const a={children:new Map,isWord:!1};for(const s of r.split(" ")){let o=a;for(const d of s){let f=o.children.get(d);f||(f={children:new Map,isWord:!1},o.children.set(d,f)),o=f}o.isWord=!0}return a}function Pe(r){if(r.length===0)return null;const a=new Set(r.map(o=>o.row)),s=new Set(r.map(o=>o.col));return a.size>1&&s.size>1?null:a.size===1?"across":"down"}function re(r,a,s,o){return a.find(f=>f.row===s&&f.col===o)??r[s][o]}function ue(r,a,s,o,d,f){let e=s,c=o;for(;U(e-d,c-f)&&re(r,a,e-d,c-f);)e-=d,c-=f;const p=[];for(;U(e,c)&&re(r,a,e,c);)p.push({row:e,col:c,...re(r,a,e,c)}),e+=d,c+=f;return p}function ke(r,a,{isFirstMove:s}){if(a.length===0)return{valid:!1,reason:"No tiles placed."};if(new Set(a.map(b=>`${b.row},${b.col}`)).size!==a.length)return{valid:!1,reason:"Two tiles were placed on the same square."};for(const b of a)if(r[b.row][b.col])return{valid:!1,reason:"A tile is already on that square."};const d=Pe(a);if(!d)return{valid:!1,reason:"Tiles must be placed in a single row or column."};const f=d==="down"?1:0,e=d==="across"?1:0,c=a.slice().sort((b,u)=>b.row-u.row||b.col-u.col),p=c[0],x=c[c.length-1];let y=p.row,A=p.col;for(;y!==x.row||A!==x.col;){if(!re(r,a,y,A))return{valid:!1,reason:"There is a gap in the line of tiles."};y+=f,A+=e}if(s){if(!a.some(u=>u.row===q&&u.col===q))return{valid:!1,reason:"The first word must cover the centre square."}}else if(!a.some(u=>[[u.row-1,u.col],[u.row+1,u.col],[u.row,u.col-1],[u.row,u.col+1]].some(([N,W])=>U(N,W)&&r[N][W])))return{valid:!1,reason:"The word must connect to a tile already on the board."};const C=ue(r,a,p.row,p.col,f,e),$=[];C.length>=2&&$.push({letters:C.map(b=>b.letter).join(""),cells:C});const I=f===0?1:0,_=e===0?1:0;for(const b of a){const u=ue(r,a,b.row,b.col,I,_);u.length>=2&&$.push({letters:u.map(k=>k.letter).join(""),cells:u})}return $.length===0?{valid:!1,reason:"That does not form a word."}:{valid:!0,words:$}}function ve(r,a){return r.every(s=>a.has(s.letters))}function je(r,a){const s=new Set(a.map(d=>`${d.row},${d.col}`));let o=0;for(const d of r){let f=0,e=1;for(const c of d.cells){let p=c.value;if(s.has(`${c.row},${c.col}`)){const x=Se(c.row,c.col);x==="DL"&&(p*=2),x==="TL"&&(p*=3),x==="QL"&&(p*=4),x==="DW"&&(e*=2),x==="TW"&&(e*=3),x==="QW"&&(e*=4)}f+=p}o+=f*e}return a.length===we&&(o+=50),o}function Oe(r){const a=[];let s=!1;for(let o=0;o<F;o++)for(let d=0;d<F;d++)if(r[o][d]){s=!0;break}if(!s)return[[q,q]];for(let o=0;o<F;o++)for(let d=0;d<F;d++){if(r[o][d])continue;[[o-1,d],[o+1,d],[o,d-1],[o,d+1]].some(([e,c])=>U(e,c)&&r[e][c])&&a.push([o,d])}return a}function he(r,a,s,o,d,f,e){const c=[];let p=a-o,x=s-d;for(;U(p,x)&&r[p][x];)c.unshift(r[p][x].letter),p-=o,x-=d;const y=[];for(p=a+o,x=s+d;U(p,x)&&r[p][x];)y.push(r[p][x].letter),p+=o,x+=d;if(c.length===0&&y.length===0)return null;const A=new Set;for(const C of e){const $=[...c,C,...y].join("");f.has($)&&A.add(C)}return A}function fe(r,a,s,o,d,f,e,c,p,x,y){const A="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),C=e===0?1:0,$=c===0?1:0;function I(m,E){if(m.length===0||E.length<2)return;const D=m.map(S=>`${S.row}
1,${S.col}:${S.letter}`).sort().join("|");if(x.has(D))return;x.add(D);const R=ke(r,m,{isFirstMove:y});R.valid&&ve(R.words,o)&&p.push({placements:m,words:R.words,score:je(R.words,m)})}function _(m,E,D){const R=[],S=new Set;for(let M=0;M<m.length;M++){const L=m[M],V=L===B?A:[L];for(const T of V)L!==B&&S.has(T)||E.children.get(T)&&(D&&!D.has(T)||R.push({i:M,tile:L,letter:T,next:E.children.get(T)}));L!==B&&S.add(L)}return R}function b(m,E,D,R,S,M){if(!U(m,E)){I(R,M);return}const L=r[m][E];if(L){const T=D.children.get(L.letter);if(!T)return;b(m+e,E+c,T,R,S,M+L.letter);return}if(I(R,M),S.length===0)return;const V=he(r,m,E,C,$,o,A);for(const{i:T,letter:Y,next:Z}of _(S,D,V)){const K=S[T],X={row:m,col:E,letter:Y,value:J(K===B?null:Y),blank:K===B},H=S.slice(0,T).concat(S.slice(T+1));b(m+e,E+c,Z,[...R,X],H,M+Y)}}function u(m,E,D,R,S,M,L){if(S.length===m){b(d,f,R,S,M,L);return}const V=he(r,E,D,C,$,o,A);for(const{i:T,letter:Y,next:Z}of _(M,R,V)){const K=M[T],X={row:E,col:D,letter:Y,value:J(K===B?null:Y),blank:K===B},H=M.slice(0,T).concat(M.slice(T+1));u(m,E+e,D+c,Z,[...S,X],H,L+Y)}}let k=0,N=d-e,W=f-c;for(;U(N,W)&&!r[N][W];)k++,N-=e,W-=c;k=Math.min(k,a.length);for(let m=0;m<=k;m++)u(m,d-e*m,f-c*m,s,[],a,"")}function ge(r,a,s,o){const d=[],f=new Set,e=!r.some(c=>c.some(Boolean));for(const[c,p]of Oe(r))fe(r,a,s,o,c,p,0,1,d,f,e),fe(r,a,s,o,c,p,1,0,d,f,e);return d}function G(r){return r.reduce((a,s)=>a+J(s),0)}function pe(r,a,s,o){return a.length===0?{playerScore:r+G(o),aiScore:s-G(o)}:o.length===0?{playerScore:r-G(a),aiScore:s+G(a)}:{playerScore:r-G(a),aiScore:s-G(o)}}const ce=[{id:"easy",label:"Easy",description:"Plays a weak word most turns, sometimes passing up better ones on purpose."},{id:"medium",label:"Medium",description:"Plays a reasonable word, chosen from the better half of what it can find."},{id:"hard",label:"Hard",description:"Always plays the highest-scoring word it can find on the turn. It does not plan ahead."}];function me(r,a){if(r.length===0)return null;const s=r.slice().sort((d,f)=>d.score-f.score);if(a==="hard")return s[s.length-1];if(a==="medium"){const d=s.slice(Math.floor(s.length/2));return d[Math.floor(Math.random()*d.length)]}const o=s.slice(0,Math.max(1,Math.ceil(s.length/2)));return o[Math.floor(Math.random()*o.length)]}const He=ce.map(r=>[r.id,r.label]),Ne="wormhole:word-tiles:scores",ae=()=>({wins:0,draws:0,losses:0,best:0}),Qe="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),_e={TW:"TW",DW:"DW",TL:"TL",DL:"DL",QW:"QW",QL:"QL"},z={TW:"bg-rose-500 text-white",DW:"bg-orange-300 text-orange-900",TL:"bg-sky-500 text-white",DL:"bg-sky-200 text-sky-900",QW:"bg-teal-700 text-white",QL:"bg-teal-400 text-white"},Ye=[["â
","bg-orange-300 text-orange-900","Centre â first word must cover this"],["DL",z.DL,"Double letter"],["TL",z.TL,"Triple letter"],["DW",z.DW,"Double word"],["TW",z.TW,"Triple word"],["QL",z.QL,"Quadruple letter (outer ring only)"],["QW",z.QW,"Quadruple word (outer ring only)"]];function Ke(){try{const r=JSON.parse(localStorage.getItem(Ne));return r&&typeof r=="object"?r:{}}catch{return{}}}function xe(r){try{localStorage.setItem(Ne,JSON.stringify(r))}catch{}}const Te="wormhole:word-tiles:prefs",le=()=>({fullWidth:!1,showTwoLetterWords:!1,standardHintsEnabled:!1,bestHintsEnabled:!1});function Fe(){try{const r=JSON.parse(localStorage.getItem(Te));return r&&typeof r=="object"?{...le(),...r}:le()}catch{return le()}}function qe(r){try{localStorage.setItem(Te,JSON.stringify(r))}catch{}}function be(r){const{drawn:a,remaining:s}=ee(r,we);return{rack:a,bag:s}}function Ue({difficultyId:r,dictionary:a,recordResult:s,fullWidth:o,standardHintsEnabled:d,bestHintsEnabled:f}){const[e,c]=O.useState(()=>{const n=ne($e()),t=be(n),i=be(t.bag);return{board:Be(),bag:i.bag,playerRack:t.rack,aiRack:i.rack,playerScore:0,aiScore:0,turn:"player",pending:[],selected:null,message:"Your turn â pick a tile, then a square on the board.",error:null,passes:0,over:!1,lastAiWords:null,exchanging:!1,exchangeSelection:[],hint:null}}),p=O.useRef(!1),x=o?"w-7 h-7 sm:w-10 sm:h-10 lg:w-12 lg:h-12":"w-5 h-5 sm:w-7 sm:h-7",y=o?"text-xs sm:text-base lg:text-lg":"text-[9px] sm:text-xs",A=o?"text-[8px] sm:text-[10px] lg:text-xs":"text-[6px] sm:text-[8px]",C=o?"w-12 h-12 sm:w-14 sm:h-14 text-xl sm:text-2xl":"w-9 h-9 sm:w-10 sm:h-10 text-lg",$=o?"text-xs sm:text-sm":"text-[10px] sm:text-xs",I=d||f,_=O.useMemo(()=>
1{if(!I||!e.hint||e.hint.none)return null;const n=new Map;for(const t of e.hint.placements)n.set(`${t.row},${t.col}`,t.letter);return n},[I,e.hint]),b=!e.board.some(n=>n.some(Boolean)),u=O.useMemo(()=>{const n=e.board.map(t=>t.slice());for(const t of e.pending)n[t.row][t.col]={letter:t.letter,value:t.value,blank:t.blank,pending:!0};return n},[e.board,e.pending]);O.useEffect(()=>{if(!e.over||p.current)return;p.current=!0;const n=e.playerScore>e.aiScore?"win":e.playerScore<e.aiScore?"loss":"draw";s(n,e.playerScore)},[e.over]);function k(n){if(!(e.turn!=="player"||e.over)){if(e.exchanging){c(t=>({...t,exchangeSelection:t.exchangeSelection.includes(n)?t.exchangeSelection.filter(i=>i!==n):[...t.exchangeSelection,n]}));return}c(t=>({...t,selected:t.selected===n?null:n,error:null}))}}function N(n){c(t=>{if(typeof t.selected!="object"||t.selected===null)return t;const{row:i,col:h,rackIndex:g}=t.selected;return W(t,i,h,g,n,!0)})}function W(n,t,i,h,g,v){const w=n.playerRack.slice();return w.splice(h,1),{...n,playerRack:w,pending:[...n.pending,{row:t,col:i,letter:g,value:J(v?null:g),blank:v,rackIndex:h}],selected:null,error:null,hint:null}}function m(n,t){if(e.turn!=="player"||e.over||e.board[n][t]||e.selected!==null&&typeof e.selected=="object")return;const i=e.pending.find(g=>g.row===n&&g.col===t);if(i){c(g=>({...g,pending:g.pending.filter(v=>!(v.row===n&&v.col===t)),playerRack:ie(g.playerRack,i.rackIndex,i.blank?B:i.letter),error:null,hint:null}));return}if(e.selected===null)return;const h=e.playerRack[e.selected];if(h===B){c(g=>({...g,selected:{row:n,col:t,rackIndex:g.selected}}));return}c(g=>W(g,n,t,g.selected,h,!1))}function E(){c(n=>{let t=n.playerRack.slice();for(const i of n.pending.slice().sort((h,g)=>h.rackIndex-g.rackIndex))t=ie(t,i.rackIndex,i.blank?B:i.letter);return{...n,pending:[],playerRack:t,selected:null,error:null,hint:null}})}function D(n){c(t=>{if(t.turn!=="player"||t.over||t.pending.length>0)return t;const i=ge(t.board,t.playerRack,a.trie,a.wordSet),h=me(i,n==="best"?"hard":r);return{...t,hint:h?{mode:n,placements:h.placements,words:h.words,score:h.score}:{mode:n,none:!0}}})}function R(){c(n=>({...n,playerRack:ne(n.playerRack)}))}function S(n,t){const i={...n,hint:null},h=t?0:i.passes+1,g=h>=2;if(i.bag.length===0&&i.playerRack.length===0||g){const w=pe(i.playerScore,i.playerRack,i.aiScore,i.aiRack);return{...i,...w,over:!0,passes:h,message:w.playerScore===w.aiScore?"It's a draw.":w.playerScore>w.aiScore?"You win!":"The computer wins."}}return{...i,passes:h,turn:"ai",message:"The computer is thinkingâ¦"}}function M(){if(e.pending.length===0){c(t=>({...t,error:"Place at least one tile first."}));return}const n=ke(e.board,e.pending,{isFirstMove:b});if(!n.valid){c(t=>({...t,error:n.reason}));return}if(!ve(n.words,a.wordSet)){const t=n.words.find(i=>!a.wordSet.has(i.letters));c(i=>({...i,error:`"${t.letters}" is not in the dictionary.`}));return}c(t=>{const i=je(n.words,t.pending),h=t.board.map(P=>P.slice());for(const P of t.pending)h[P.row][P.col]={letter:P.letter,value:P.value,blank:P.blank};const{drawn:g,remaining:v}=ee(t.bag,t.pending.length),w=S({...t,board:h,bag:v,playerRack:[...t.playerRack,...g],playerScore:t.playerScore+i,pending:[]},!0);return{...w,message:w.over?w.message:`You played ${n.words.map(P=>P.letters).join(", ")} for ${i}. The computer is thinkingâ¦`}})}function L(){c(n=>S(n.pending.length?{...n,playerRack:V(n),pending:[]}:n,!1))}function V(n){let t=n.playerRack.slice();for(const i of n.pending.slice().sort((h,g)=>h.rackIndex-g.rackIndex))t=ie(t,i.rackIndex,i.blank?B:i.letter);return t}function T(){c(n=>({...n,exchanging:!0,exchangeSelection:[],selected:null,error:null,hint:null}))}function Y(){c(n=>({...n,exchanging:!1,exchangeSelection:[]}))}function Z(){c(n=>{if(n.exchangeSelection.length===0||n.bag.length===0)return{...n,exchanging:!1,exchangeSelection:[]};const t=n.exchangeSelection.map(w=>n.playerRack[w]),i=n.playerRack.filter((w,P)=>!n.exchangeSelection.includes(P)),h=ne([...n.bag,...t]),{drawn:g,remaining:v}=ee(h,t.length);return S({...n,bag:v,playerRack:[...i,...g],exchanging:!1,exchangeSelection:[]},!1)})}O.useEffect(()=>{if(e.turn!=="ai"||e.over)return;const n=setTimeout(()=>{c(t=>{const i=ge(t.board,t.aiRack,a.trie,a.wordSet),h=me(i,r);if(!h){if(t.bag.length>0){const Re=ne([...t.bag,...t.aiRack]),{drawn:Me,remaining:Ce}=ee(Re,t.aiRack.length),oe=K({...t,bag:Ce,aiRack:Me},!1);return{...oe,lastAiWords:null,message:oe.over?oe.message:"The computer had no play and exchanged tiles. Your turn."}}const j=K(t,!1);return{...j,lastAiWords:null,message:j.over?j.message:"The computer had no play and passed. Your turn."}}const g=t.board.map(j=>j.slice());for(const j of h.placements)g[j.row][j.col]={letter:j.letter,value:j.value,blank:j.blank};const v=h.placements.map(j=>j.blank?B:j.letter);let w=t.aiRack.slice();for(const j of v)w.splice(w.indexOf(j),1);const{drawn:P,remaining:Ee}=ee(t.bag,h.placements.length),se=K({...t,board:g,bag:Ee,aiRack:[...w,...P],aiScore:t.aiScore+h.score},!0);return{...se,lastAiWords:h.words.map(j=>j.letters),message:se.over?se.message:`The computer played ${h.words.map(j=>j.letters).join(", ")} for ${h.score}. Your turn.`}}
1)},500+Math.random()*400);return()=>clearTimeout(n)},[e.turn,e.over]);function K(n,t){const i=t?0:n.passes+1,h=i>=2;if(n.bag.length===0&&n.aiRack.length===0||h){const v=pe(n.playerScore,n.playerRack,n.aiScore,n.aiRack);return{...n,...v,over:!0,passes:i,message:v.playerScore===v.aiScore?"It's a draw.":v.playerScore>v.aiScore?"You win!":"The computer wins."}}return{...n,passes:i,turn:"player"}}const X=e.turn==="player"&&!e.over&&e.pending.length>0,H=e.turn==="player"&&!e.over&&!e.exchanging;return l.jsxs("div",{className:"flex flex-col items-center gap-4",children:[l.jsx("p",{role:"status","aria-live":"polite",className:"text-base font-medium text-gray-900 min-h-[1.75rem] text-center",children:e.message}),l.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-x-6 gap-y-1 text-sm font-mono",children:[l.jsxs("span",{children:["You: ",e.playerScore]}),l.jsxs("span",{children:["Computer: ",e.aiScore]}),l.jsxs("span",{children:["Tiles left in bag: ",e.bag.length]})]}),l.jsx("div",{className:"max-w-full overflow-x-auto",children:l.jsx("div",{className:"inline-grid border border-gray-400",style:{gridTemplateColumns:`repeat(${F}, minmax(0, 1fr))`},children:u.map((n,t)=>n.map((i,h)=>{const g=Se(t,h),v=t===q&&h===q,w=!i&&_?_.get(`${t},${h}`):null;return l.jsxs("button",{type:"button",onClick:()=>m(t,h),disabled:!H||!!i&&!i.pending,className:`${x} border flex items-center justify-center ${y} font-bold relative select-none ${w&&!i?"border-2 border-dashed border-purple-400":"border-gray-200"} ${i?i.pending?"bg-indigo-200 text-indigo-900":"bg-yellow-100 text-gray-900":w?"bg-purple-50 text-purple-400":g?z[g]:"bg-green-50 hover:bg-green-100"}`,children:[i?i.letter:w||(v?"â
":g?_e[g]:""),i&&!i.blank&&l.jsx("span",{className:`absolute bottom-0 right-0.5 ${A} font-normal leading-none`,children:J(i.letter)})]},`${t}-${h}`)}))})}),l.jsxs("div",{className:"flex flex-col items-center gap-2",children:[l.jsx("div",{className:"flex gap-1.5",children:e.playerRack.map((n,t)=>l.jsxs("button",{type:"button",onClick:()=>k(t),disabled:!H&&!e.exchanging,"aria-pressed":e.selected===t||e.exchangeSelection.includes(t),className:`${C} rounded border-2 font-bold relative flex items-center justify-center ${e.selected===t||e.exchangeSelection.includes(t)?"bg-indigo-500 text-white border-indigo-600":"bg-yellow-100 border-yellow-300 text-gray-900 hover:bg-yellow-200"}`,children:[n===B?"?":n,l.jsx("span",{className:`absolute bottom-0 right-0.5 ${$} font-normal leading-none`,children:J(n)})]},t))}),typeof e.selected=="object"&&e.selected!==null&&l.jsxs("div",{className:"flex flex-wrap justify-center gap-1 max-w-xs",children:[l.jsx("span",{className:"w-full text-center text-xs text-gray-600",children:"Choose a letter for the blank:"}),Qe.map(n=>l.jsx("button",{type:"button",onClick:()=>N(n),className:Q,children:n},n))]})]}),e.exchanging?l.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-2",children:[l.jsx("span",{className:"text-sm text-gray-700",children:"Pick tiles above to swap, then:"}),l.jsx("button",{type:"button",onClick:Z,disabled:e.exchangeSelection.length===0,className:Q,children:"Exchange selected"}),l.jsx("button",{type:"button",onClick:Y,className:Q,children:"Cancel"})]}):l.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-2",children:[l.jsx("button",{type:"button",onClick:M,disabled:!X,className:Q,children:"Play word"}),l.jsx("button",{type:"button",onClick:E,disabled:!H||e.pending.length===0,className:Q,children:"Recall tiles"}),l.jsx("button",{type:"button",onClick:R,disabled:!H,className:Q,children:"Shuffle rack"}),l.jsx("button",{type:"button",onClick:T,disabled:!H||e.bag.length===0,className:Q,children:"Exchange tiles"}),l.jsx("button",{type:"button",onClick:L,disabled:!H,className:Q,children:"Pass"}),d&&l.jsx("button",{type:"button",onClick:()=>D("standard"),disabled:!H||e.pending.length>0,className:Q,children:"Suggest a word"}),f&&l.jsx("button",{type:"button",onClick:()=>D("best"),disabled:!H||e.pending.length>0,className:Q,children:"Suggest the best word"})]}),e.error&&l.jsx(de,{tone:"danger",children:e.error}),I&&e.hint&&l.jsx(de,{tone:"info",children:e.hint.none?"No suggestion available for this rack â try exchanging tiles.":`${e.hint.mode==="best"?"Best hint":"Hint"}: try ${e.hint.words.map(n=>n.letters).join(", ")} for ${e.hint.score} points â shown as dashed letters on the board.`})]})}function ie(r,a,s){const o=r.slice();return o.splice(Math.min(a,o.length),0,s),o}function Xe({section:r,item:a}){const[s,o]=O.useState("medium"),[d,f]=O.useState(null),[e,c]=O.useState(0),[p,x]=O.useState(Ke),[y,A]=O.useState(Fe),C=p[s]??ae();O.useEffect(()=>{let u=!1;return We(()=>import("./wordTilesDictionary-cllqw-Ov.js"),[]).then(k=>{if(u)return;const N=k.default.split(" ");f({trie:Ie(k.default),wordSet:new Set(N)})}),()=>{u=!0}},[]);const $=O.useMemo(()=>d?Array.from(d.wordSet).filter(u=>u.length===2).sort():[],[d]);function I(u){A(k=>{const N={...k,[u]:!k[u]};return qe(N),N})}function _(u,k){x(N=>{const W={...ae(),...N[s]},m={...N,[s]:W};return u==="win"?W.wins++:u==="loss"?W.losses++:W.draws++,k>W.best&&(W.best=k),xe(m),m})}function b(){const u={...p,[s]:ae()};x(u),xe(u)}return l.jsxs(De,{section:r,item:a,fullWidth:y.fullWidth,children:[l.jsxs("div",{className:"flex flex-wrap items-start gap-6",children:[l.jsxs("div",{children:[l.jsx("span",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Difficulty"}),l.jsx(Le,{value:s,onChange:o,options:He,label:"Difficulty"}),l.jsx("p",{className:"mt-1 text-xs text-gray-500 max-w-xs",children:ce.find(u=>u.id===s).description})]}),l.jsx("button",{type:"button",onClick:()=>c(u=>u+1),className:Q,children:"New game"})]}),l.jsxs("div",{className:"flex flex-wrap items-center gap-x-6 gap-y-2",children:[l.jsx(te,{id:"wt-full-width",checked:y.fullWidth,onChange:()=>I("fullWidth"),children:"Full width board (bigger tiles)"}),l.jsx(te,{id:"wt-two-letter",checked:y.showTwoLetterWords,onChange:()=>I("showTwoLetterWords"),children:"Show two-letter words"}),l.jsx(te,{id:"wt-hints",checked:y.standardHintsEnabled,onChange:()=>I("standardHintsEnabled"),children:"Enable word suggestions (Standard)"}),l.jsx(te,{id:"wt-best-hints",checked:y.bestHintsEnabled,onChange:()=>I("bestHintsEnabled"),children:"Best word suggestions (Cheat)"})]}),l.jsx("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-gray-600",children:Ye.map(([u,k,N])=>l.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[l.jsx("span",{className:`inline-flex items-center justify-center w-5 h-5 rounded-sm text-[9px] font-bold ${k}`,children:u}),N]},u))}),y.showTwoLetterWords&&d&&l.jsxs("div",{children:[l.jsxs("p",{className:"text-sm font-medium text-gray-700 mb-2",children:["Two-letter words (",$.length,")"]}),l.jsx("div",{className:"flex flex-wrap gap-1.5 text-xs font-mono",children:$.map(u=>l.jsx("span",{className:"px-1.5 py-0.5 bg-gray-100 rounded border border-gray-200",children:u},u))})]}),d?l.jsx(Ue,{difficultyId:s,dictionary:d,recordResult:_,fullWidth:y.fullWidth,standardHintsEnabled:y.standardHintsEnabled,bestHintsEnabled:y.bestHintsEnabled},`${s}-${e}`):l.jsx("p",{className:"text-sm text-gray-500",children:"Loading dictionaryâ¦"}),l.jsxs("div",{className:"border-t border-gray-200 pt-4",children:[l.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[l.jsxs("p",{className:"text-sm text-gray-700",children:["At ",l.jsx("span",{className:"font-medium",children:ce.find(u=>u.id===s).label}),":"," ",l.jsxs("span",{className:"font-medium text-green-700",children:[C.wins," won"]}),","," ",l.jsxs("span",{className:"font-medium text-gray-600",children:[C.draws," drawn"]}),","," ",l.jsxs("span",{className:"font-medium text-red-700",children:[C.losses," lost"]}),","," ","best score ",l.jsx("span",{className:"font-medium text-gray-900",children:C.best})]}),l.jsx("button",{type:"button",onClick:b,className:Q,children:"Reset stats"})]}),l.jsx("p",{className:"mt-2 text-xs text-gray-500",children:"You always go first. Pick a tile from your rack, then a square on the board â placing a blank (?) asks you to choose the letter it stands for. The game ends when the bag empties and someone plays their last tile, or when both players pass or exch
1ange in a row. Hard picks the single highest-scoring word it can find each turn; it does not plan ahead or hold tiles back for a bigger play later. Standard suggestions are found the same way the computer opponent plays at your chosen difficulty; Best suggestions always take the single highest-scoring word the search can find this turn, skipping the difficulty setting entirely. Neither looks ahead â both just show you a word and where it fits (as dashed letters on the board) without placing it for you. Your scores and these options are kept in this browser only."})]}),l.jsxs("div",{className:"border-t border-gray-200 pt-4 text-xs text-gray-500 space-y-1",children:[l.jsx("p",{className:"font-medium text-gray-600",children:"Dictionary source and licence"}),l.jsxs("p",{children:["The word list is generated from the"," ",l.jsx("a",{href:"https://github.com/en-wl/wordlist",target:"_blank",rel:"noopener noreferrer",className:"text-indigo-600 hover:text-indigo-800",children:"English Speller Database (ESDB, formerly SCOWL)"}),", combining American and British (-ise/-ize) spellings, with proper nouns and possessive forms removed."]}),l.jsx("p",{children:"Copyright 2000â2026 by Kevin Atkinson. Permission to use, copy, modify, distribute and sell any part of the ESDB, or word lists created from it, is granted without fee, provided the copyright notice appears in all copies and both the copyright notice and this notice appear in supporting documentation. Kevin Atkinson makes no representations about the suitability of this database for any purpose; it is provided âas isâ without express or implied warranty. The primary source of words for ESDB is 12dicts and ENABLE2K, both in the Public Domain â Alan Beale is the author of 12dicts and a major contributor to ENABLE2K."})]})]})}export{Xe as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.