
Uma IA que cria problemas
As IAs de go, gomoku e Othello que fizemos até agora eram adversárias que jogam contra pessoas. As palavras cruzadas são diferentes. A IA não resolve os problemas nem compete com as pessoas; ela cria problemas para as pessoas resolverem. Os problemas são palavras cruzadas em coreano, então cada casa da grade guarda uma sílaba coreana.
A web foi feita na mesma estrutura dos outros jogos.
- Fica em crossword.mariago.kr. Roda na porta 3009 do Mac de casa, e o nginx do IDC faz a ponte.
- Ao escolher a dificuldade no lobby e entrar em uma sala de jogo, uma grade nova é criada.
- A grade e cada uma das entradas ficam salvas no SQLite como registro da partida.
A primeira ordem: palavras → pistas → grade
No começo, ela escolhia palavras de um banco de palavras, acrescentava uma pista a cada palavra e depois encaixava essas palavras na grade. Se uma palavra tinha uma sílaba igual à de uma palavra já colocada, era posta cruzando naquele ponto.
As grades que saíram não eram palavras cruzadas.
- Uma grade 12×12 tinha só 7 ou 8 pistas. A maior parte da grade era de casas pretas.
- A maioria das respostas tinha duas sílabas.
- As palavras se ligavam só pela primeira e pela última sílaba e se alinhavam como uma escada inclinada. Quase não havia cruzamentos pelas sílabas do meio, como "keuriseumaseu" (Natal) e "alpeuseu" (Alpes) se cruzando na sílaba comum "seu".
- As palavras se concentravam só no meio da grade.
- Quando joguei duas grades difíceis seguidas, todas as palavras menos uma já tinham aparecido na grade anterior.
As 24 grades salvas no primeiro dia
O banco de registros de partidas ainda guarda 24 grades criadas naquele dia. Todas são grades difíceis 12×12.
- Tinham de 6 a 8 palavras, 6,8 em média.
- As casas brancas eram em média 6,5% da grade.
- 76% das respostas tinham duas sílabas.
- Nenhuma grade tinha simetria de 180°.
Em 22 das 24 grades, apertei de novo para criar uma grade nova sem preencher nenhuma casa. Gerei outra assim que vi a grade.
O que tentamos corrigir
- Exigimos 15 ou mais pistas horizontais e verticais. Passou nos testes, mas a tela continuava mostrando grades com 8 pistas. O lobby continuava reabrindo uma grade criada antes.
- Criamos um agente de texto que roda o gerador diretamente e imprime a grade e a lista de pistas em texto. Ele também verifica as grades do banco de registros e marca as ilhas de palavras de duas sílabas.
- Também surgiu um método que preenchia a grade repetindo blocos em forma de cruz com três sílabas. É a imagem no alto à direita. O número de pistas aumentou, mas todas as respostas tinham três sílabas e os blocos não se ligavam entre si. Foi uma ideia bem típica de IA, e não existem palavras cruzadas assim no mundo.
Decidimos mudar a ordem
Se você coloca as palavras primeiro, o formato da grade só vem como consequência, e não há como controlá-lo. Por isso decidimos montar a grade primeiro, depois escolher palavras que caibam no comprimento das casas e, por último, escrever as pistas.
O código real desta etapa
Esta é a parte em que o agente de texto verifica as grades salvas. Se o comprimento médio for curto ou não houver cruzamentos no meio, ele imprime que é preciso um jogo novo.
scripts/text-agent.ts
for (const row of rows) {
let across = 0;
let down = 0;
let mid = 0;
let avg = 0;
try {
const puzzle = JSON.parse(row.puzzle_json) as Puzzle;
across = puzzle.across?.length ?? 0;
down = puzzle.down?.length ?? 0;
mid = countMiddleCrosses(puzzle);
avg = avgWordLength(puzzle);
} catch {
/* ignore */
}
const mark = avg >= 2.7 && mid >= 1 ? "교차있음" : "2글자섬 ← 새 게임 필요";
console.log(
`${row.code} ${row.difficulty} ${row.size}×${row.size} ${row.status} 가로 ${across} 세로 ${down} 교차 ${mid} 평균 ${avg.toFixed(2)} ${mark} ${row.created_at}`,
);Estas são as regras do posicionador que encaixa as palavras. Uma palavra nova precisa se sobrepor a uma palavra já colocada em exatamente uma casa, e nenhuma outra sílaba pode ficar numa casa vizinha. Esse posicionador continua existindo como caminho reserva e volta a aparecer no post 3.
lib/gridFill.ts
for (const [nr, nc] of neighbors) {
if (inBoard(size, nr, nc) && grid[idx(size, nr, nc)] != null) return null;
}
}
if (intersections !== 1 || newCells < 1) return null;O próximo post é "2. Grade primeiro, palavras depois, pistas por último".
COMMENTS · CHAPTER 01
Colocar as palavras primeiro não deu palavras cruzadas 0 comentários
Ainda não há comentários. Deixe uma pergunta ou algo que queira acrescentar.
Para publicar um comentário, comece com o Google e registre um apelido e um e-mail.
Começar com o Google