Ficção Interativa com IA: Uma Nova Fronteira
A combinação de Twine com modelos de linguagem (LLMs) abre possibilidades fascinantes: personagens que respondem de forma única a cada jogador, descrições que se adaptam ao contexto, ou mesmo uma IA que coescreve partes da narrativa em tempo real.
Neste tutorial, usaremos o formato SugarCube (mais amigável para JavaScript) e integraremos com uma API de LLM.
Requisitos
Este tutorial requer conhecimento básico de JavaScript e acesso a uma API de LLM (OpenAI, Anthropic ou Ollama local). Chaves de API da OpenAI têm custo; o Ollama permite rodar modelos localmente e gratuitamente.Configurando o Story Format SugarCube
- No Twine, abra as configurações da story (ícone ≡ → “Change Story Format”)
- Selecione SugarCube 2.36
O SugarCube tem suporte nativo a JavaScript e macros como <<script>>.
Opção A: Usando a API da OpenAI
Passage: “Config” (execute uma vez)
<<silently>>
<<set $apiKey to "SUA_CHAVE_OPENAI_AQUI">>
<<set $historico to []>>
<<set $nomePersonagem to "Viajante">>
<</silently>>
Segurança!
Nunca publique uma história com sua chave de API exposta no código. Para produção, use um servidor proxy que mantém a chave secreta. Esta abordagem só é segura para uso local e desenvolvimento.Macro JavaScript para chamar a API
Crie um passage chamado "setup" (marcado como JavaScript):
|
|
Usando a IA em um Passage
:: Sala Misteriosa
<<set $localAtual to "uma sala de pedra com tochas apagadas">>
<<set _descricao to "">>
<<button "✨ Descreva este local com IA">>
<<script>>
const loader = document.getElementById("ia-output");
loader.innerHTML = "<em>A IA está narrando…</em>";
chamarIA(
"Descreva este local de forma atmosférica para um jogador de RPG textual",
State.variables.localAtual
).then(texto => {
loader.innerHTML = texto;
State.variables.descricaoIA = texto;
});
<</script>>
<</button>>
<div id="ia-output" style="margin:1em 0;padding:1em;background:rgba(255,255,255,0.05);border-left:3px solid purple;min-height:3em;border-radius:4px">
<em>Clique no botão para gerar uma descrição narrativa.</em>
</div>
[[Explorar mais fundo]]
[[Sair correndo]]
Opção B: Usando Ollama (Gratuito, Local)
O Ollama permite rodar modelos como Llama 3, Mistral e Gemma localmente, sem custo.
Instalação do Ollama
|
|
Chamada à API local no SugarCube
|
|
CORS com Ollama
Para chamadas do Twine local ao Ollama, você pode precisar iniciar o Ollama comOLLAMA_ORIGINS=* ollama serve para permitir requisições cross-origin.
Sistema de Personagem NPC com Memória
Um caso de uso poderoso: um NPC que “lembra” das ações do jogador.
:: Taverna — Falar com a Estalajadeira
<<if $falasComInnkeeper is undefined>>
<<set $falasComInnkeeper to []>>
<</if>>
<<textbox "$mensagemJogador" "O que você diz para a estalajadeira?">>
<<button "Falar">>
<<script>>
const msg = State.variables.mensagemJogador;
const historico = State.variables.falasComInnkeeper;
const contexto = historico.length > 0
? `Histórico: ${historico.slice(-3).join(" | ")}`
: "Primeiro encontro";
chamarIALocal(
`Você é uma estalajadeira desconfiada em uma fantasia sombria.
${contexto}. O jogador diz: "${msg}". Responda em 1-2 frases curtas e caracteristicamente.`
).then(resposta => {
document.getElementById("npc-fala").innerHTML =
`<strong>Estalajadeira:</strong> "${resposta}"`;
State.variables.falasComInnkeeper.push(`Jogador: ${msg} | NPC: ${resposta}`);
});
<</script>>
<</button>>
<div id="npc-fala" style="margin:1em 0;font-style:italic;color:#d4a">
<em>A estalajadeira aguarda você falar.</em>
</div>
[[Pedir um quarto]]
[[Perguntar sobre rumores]]
[[Sair da taverna]]
Boas Práticas
| Prática | Motivo |
|---|---|
Limite max_tokens |
Evita respostas longas demais e custos altos |
| Mostre feedback de carregamento | A API pode demorar 1-3 segundos |
| Sempre tenha fallback | A API pode falhar; ofereça conteúdo padrão |
| Use temperatura 0.7–0.9 | Equilibra criatividade e coerência |
| Forneça contexto no system prompt | Quanto mais contexto, melhor a resposta |
| Teste com Ollama primeiro | Evite custos de API durante desenvolvimento |