Um
dos modelos mais tradicionais de jogos de raciocínio ficou
conhecido no Brasil como adventures
(que numa tradução mais livre significa "jogos
de aventuras"). Havia então uma distinção
clara entre esses jogos e os demais, chamados de arcades (Space
Invaders, Pong, Penetrator, Pacman, etc).
Com o desenvolvimento de novas técnicas e novos recursos
de hardware à disposição dos desenvolvedores,
os jogos de aventuras evoluiram para modelos mais sofisticados
e hoje eles englobam desde os jogos Point & Click,
até os modernos jogos MMORPGs, passando
pelos tradicionais MUDs e Adventures.
A
essência do termo (adventure)
então passou a indicar um tipo de jogo onde o jogador tem
controles sofisticados sobre o que pode ser feito, como ação
do seu personagem, englobando inclusive coisas que supostamente
poderiam vir a ser realizadas (deixando portanto a imaginação
do jogador livre e solta).
A base desse modelo está apoiada num sistema de reconhecimento
de comando digitado, uma vez que as demais formas (teclas de ação,
áreas clicáveis, lista de ações, etc)
não conseguem resolver eficientemente todas as situações
de um jogo desta natureza. O ideal é portanto mesclar os
sistemas, para que o jogador decida como seria melhor resolvida
a situação ou problema atual que ele enfrenta.
O
que vamos mostrar nesta matéria é uma alternativa
para um modelo de interpretador de comandos, que pode depois ser
implementado com recursos específicos para determinados
jogos. Ele se baseia no reconhecimento (a partir de uma frase
digitada) de verbo mais dois objetos. O uso de dois e não
apenas um objeto na frase nos permite construções
extremamente complexas e requintadas, como por exemplo:
pegue
a mala pequena
pegue a caneta azul
coloque a caneta na mala
O
sistema exige, no entanto, que a palavra seja digitada corretamente
e por completo, para evitar situações dúbias.
Para
processar a frase, precisamos de um TMemo
(que chamaremos Frase) para a digitação
da mesma e um TLabel
(que chamaremos de Mensag) para ser usado em
resposta à ação pretendida. Dois TListBox
(um chamado Verbos e o outro Palavs)
completam o sistema básico de reconhecimento. A figura
abaixo mostra como poderia ser montado o Form deste processador.
O
TListBox Verbos
conterá a lista de ações possíveis
(ou verbos). Cada um deles deve ser definido numa linha, começando
e terminando por um sinal ":" e que
pode separar, na mesma linha, sinônimos. Assim, PEGAR
e PEGUE seriam sinônimos de uma mesma ação
e o jogador tanto poderia escrever pegue
a mala, quanto pegar
a mala. O mesmo vale para os objetos (ou palavras).
Uma
vez digitada a frase, ao pressionar a tecla Enter,
o sistema tentará identificar as palavras de tal forma
a compor três códigos (índices), sendo que
o zero (0) indicará que a palavra não foi reconhecida.
procedure TForm1.FraseKeyPress(Sender: TObject;
var Key: Char);
var
Tm: integer;
begin
Key:= UpCase(Key);
if Key = 'ç' then Key:='Ç'; if Key = 'á' then Key:='Á';
if Key = 'é' then Key:='É'; if Key = 'í' then Key:='Í';
if Key = 'ó' then Key:='Ó'; if Key = 'ú' then Key:='Ú';
if Key = 'ã' then Key:='Ã'; if Key = 'õ' then Key:='Õ';
if Key = 'â' then Key:='Â'; if Key = 'ê' then Key:='Ê';
if Key = 'ô' then Key:='Ô'; if Key = 'ü' then Key:='Ü';
if Key = 'à' then Key:='À';
if Key = chr(13) then begin
Mensag.Caption:= ''; Mensag.Repaint;
Frase.Text:= trim(Frase.Text);
if Frase.Text = '' then begin
Mensag.Caption:= 'Especifique o comando desejado.';
Frase.Text:= ''; Frase.SetFocus;
exit;
end;
DecodeFrase; Frase.Text:= ''; Frase.Repaint;
B1:= P1; B2:= P2; B3:= P3;
CdDc:= IntToHex(P1,3)+IntToHex(P2,3)+IntToHex(P3,3)+
'.txt';
Label2.Caption:= CdDc;
if LoadArq(CdDc) then begin
Memo1.Lines.LoadFromFile(CdDc);
Executar;
Frase.SetFocus;
exit;
end;
Mensag.Caption:= 'Comando desconhecido.';
Frase.SetFocus;
end;
end; |
A
procedure DecodeFrase faz esse serviço,
colocando os respectivos índices das palavras reconhecidas
em três variáveis globais (integer: P1, P2 e P3).
procedure TForm1.DecodeFrase; label Lp1,Lp2; var S,W: string; Tm: integer; Pr: boolean; begin P1:= 0; P2:= 0; P3:= 0; S:= Frase.Text; Frase.Text:= ''; Pr:= false; S:= trim(S); if S = '' then exit; Tm:= pos('-',S); if Tm = 0 then Tm:= pos(' ',S) else Pr:= true; if Tm = 0 then begin W:= S; S:= ''; end else begin W:= copy(S,1,Tm-1); S:= copy(S,Tm+1,length(S)); end; W:= ':' + W + ':';
//Verifica se é complemento de frase if Cp <> 0 then begin P1:= B1; if Cp = 1 then begin Cp:= 0; goto Lp1; end; P2:= B2; Cp:= 0; goto Lp2; end;
//Indetifica o verbo for Tm:= 0 to Verbos.Items.Count-1 do begin if pos(W,Verbos.Items[Tm]) <> 0 then begin P1:= Tm+1; //Achei paridade Break end; end; if S = '' then exit; if P1 = 0 then exit; if Pr then begin P2:= B2; Tm:= pos(' ',S); if Tm = 0 then begin W:= S; S:= ''; end else begin W:= copy(S,1,Tm-1); S:= copy(S,Tm+1,length(S)); end; goto Lp2; end;
Lp1: S:= trim(S); if S = '' then exit; Tm:= pos(' ',S); if Tm = 0 then begin W:= S; S:= ''; end else begin
W:= copy(S,1,Tm-1);
S:= copy(S,Tm+1,length(S));
end; W:= ':' + W + ':';
//Identifica primeira palavra for Tm:= 0 to Palavs.Items.Count-1 do begin if pos(W,Palavs.Items[Tm]) <> 0 then begin P2:= Tm+1; //Achei paridade Break end; end; if S = '' then exit; if P2 = 0 then goto Lp1;
Lp2: S:= trim(S); if S = '' then exit; Tm:= pos(' ',S); if Tm = 0 then begin W:= S; S:= ''; end else begin
W:= copy(S,1,Tm-1);
S:= copy(S,Tm+1,length(S));
end; W:= ':' + W + ':';
//Identifica segunda palavra for Tm:= 0 to Palavs.Items.Count-1 do begin if pos(W,Palavs.Items[Tm]) <> 0 then begin P3:= Tm+1; //Achei paridade Break end; end; if S = '' then exit; if P3 = 0 then goto Lp2; end; |
No final deste processamento temos uma string composta pelos índices
das palavras reconhecidas, convertidos em representação
hexadecimal de três dígitos (o que nos permitira
compor listas com até 4.094 verbos ou
palavras). Acrescentamos a extensão ".txt"
para que a string formada seja tratada como um arquivo texto,
onde estarão definidas as ações referentes
aquele conjunto específico de palavras.
Por
exemplo, digamos que a frase pegue
a mala resulte no aquivo 001001000.txt
e que, existindo, o mesmo é carregado para um TMemo
(Memo1), para ser processado.
procedure TForm1.Executar; var Tm,Tp: integer; begin if Memo1.Lines.Count = 0 then exit; Tm:= 0; while Tm < Memo1.Lines.Count do begin Tp:= DecodeLin(Memo1.Lines[Tm]); if Tp = -1 then inc(Tm) else Tm:= Tp; end; end; |
Cada
linha do arquivo texto é portanto um comando que deve ser
criado com um mnemônico e parâmetros. Para exemplificar
esse processo, vamos mostrar uma instrução que chamaremos
msg, cuja função é simplesmente
mostrar a mensagem parâmetro para o jogador. A sintaxe da
instrução seria:
msg
Não existe nenhuma mala aqui.
function TForm1.DecodeLin(S: string): integer; var Cmd: string; begin result:= -1; if S = '' then exit; while S[1] = ' ' do S:= copy(S,2,length(S)); Cmd:= ''; if (S = '') or (S[1] = ':') or (S[1] = '/') then exit; if pos(' ',S) = 0 then Cmd:= S else Cmd:= copy(S,1,pos(' ',S)-1); S:= copy(S,pos(' ',S)+1,length(S));
//A partir deste ponto Cmd contém o mnemônico da //instrução a ser executada, seguindo o esquema //abaixo:
//-Mensagem de avisdo --- msg texto if Cmd = 'msg' then begin Mensag.Caption:= S; exit; end; end; |
Simples assim. Daqui em diante fica por conta da imaginação
de cada desenvolvedor.
|
Download...
Clique no links para fazer
o download dos arquivos. O download desses arquivos é
exclusivo para os assinantes do club TILT. Se ainda não
é assinante, clique
aqui e saiba como assinar.
|
Fonte
completo deste exemplo |
|
|