Pirate's Adventure foi o segundo jogo criado por Scott Adams (não confundir com o autor do Dilbert). Foi escrito originalmente em BASIC para o TRS-80, inspirado nos clássicos Colossal Cave Adventure (o jogo) e Ilha do Tesouro (o livro). Para conseguir fazer o jogo rodar em um micro com 16K de Ram, Scott criou um interpretador que processa uma série de tabelas que definem verbos, nomes, objetos, locais, mensagens e ações.
Em dezembro de 1980, a revista Byte publicou um artigo com o código em BASIC do interpretador e das tabelas que definem o Pirate's Adventure. A imagem abaixo dá uma ideia do código: múltiplos comandos por linha, sem espaços entre os elementos e transbordando de GOTOs.
Em 1981 (movido por aquela animação típica da juventude) eu decifrei a maior parte do código e traduzi o interpretador para COBOL, para rodar no único computador a que eu tinha acesso (no estágio). No ano seguinte eu já tinha acesso (no trabalho) a um micro CP/M-80 e não tive dificuldade em adaptar para rodar no MBASIC.
No final dos anos 90, já existindo a internet, encontrei várias informações adicionais, como o site do Scott Adams, o if-archive e iFiction. Nestes sites você encontra tanto interpretadores como os dados para as várias aventuras publicadas pela Adventure International.
Portanto não existe dificuldade em rodar este jogo hoje em dia... a não ser que você seja um saudosista como eu e queira rodar algo bem próximo do que foi publicado na revista Byte. O interpretador BASIC que eu venho utilizando no Raspberry Pi é o Yabasic, que tem a vantagem adicional de também poder ser usado sob Windows. A sua grande desvantagem é que não possui um editor integrado, você edita o código fora dele e depois tenta rodar. Também não está disponível este "ópio do programadores" que é o depurador interativo.
Felizmente eu ainda tinha o arquivo que rodei em 1982, que de alguma forma migrou ao longo dos anos do disquete CP/M-80 de 8 polegadas para um HD externo (provavelmente passando por disquetes de 5 1/4 e 3 1/2 polegadas e um CD-Rom). Este arquivo é quase igual à listagem da revista; a principal alteração é ter espaço entre os tokens.
O primeiro passo foi um tedioso acerto das pequenas diferenças sintáticas. O maior volume foi colocar aspas nos textos dos comandos DATA que contem os dados:
6390 DATA TOO DRY. FISH VANISH.,PIRATE AWAKENS. SAYS -AYE MATEY WE BE CASTING OFF SOON- HE THEN VANISHES 6400 DATA AFTER A MONTH AT SEA WE SET ANCHOR OFF OF A SANDY BEACH. ALL ASHORE WHO'S GOING ASHORE... 6390 DATA "TOO DRY. FISH VANISH.","PIRATE AWAKENS. SAYS -AYE MATEY WE BE CASTING OFF SOON- HE THEN VANISHES" 6400 DATA "AFTER A MONTH AT SEA WE SET ANCHOR OFF OF A SANDY BEACH. ALL ASHORE WHO'S GOING ASHORE..."Uma outra alteração chata foi ter que colocar ENDIF no final dos IFs com THEN.
370 IF NV(0) <> V THEN GOTO 980 ELSE N=INT(CA(X,0)-V*150) 380 IF NV(0)=0 THEN F=0 : IF 100*RND(1) <= N THEN 400 ELSE GOTO 980 390 IF N<>NV(1) AND N<>0 THEN GOTO 980 370 IF NV(0) <> V THEN GOTO 980 ELSE N=INT(CA(X,0)-V*150) ENDIF 380 IF NV(0)=0 THEN F=0 : IF RAN(100) <= N THEN GOTO 400 ELSE GOTO 980 ENDIF : ENDIF 390 IF N<>NV(1) AND N<>0 THEN GOTO 980 ENDIFAlgumas mudanças foram mais simples, como a ordem dos parâmetros no OPEN (acabei trocando o comando OPEN pela função OPEN para poder testar se deu erro). Os comandos INPUT e PRINT tem pequenas diferenças, particularmente a necessidade de usara vírgula ao invés de ponto-e-vírgula. A manipulação de bits também exigiu algumas mudanças.
Por fim teve a parte mais complicada: o abuso dos comandos FOR/NEXT. Na teoria, estes comandos deveriam ser usados em par e aninhados corretamente. Por exemplo:
FOR X=1 TO 10 FOR Y=1 TO 5 PRINT X+Y NEXT Y NEXT XObserve a linha abaixo e tente entender o que ela faz (e o que ela deixa de fazer):
410 F1=-1 : FOR Z=0 TO IL : IF IA(Z)=-1 THEN 550 ELSE NEXT : F1=0 : GOTO 550Vamos decifrar isto:
- F1 é usado como uma variável lógica, no BASIC do TRS-80 -1 é verdadeiro. Para ser mais preciso, -1 é o resultado de uma expressão verdadeira, no IF qualquer valor diferente de 0 é verdadeiro. O YABASIC usa 1 no resultado, mas isto não atrapalhou o programa.
- IA é um vetor que armazena o local onde está cada objeto. -1 indica que o objeto está sendo carregado pelo jogador
- IL é o número de objetos (contando a partir de zero, é claro)
Neste caso dá para usar o comando BREAK para fazer uma saída limpa:
410 F1=0 412 FOR Z=0 TO IL 414 IF IA(Z)=-1 THEN F1 = -1 : BREAK : ENDIF 416 NEXT Z 418 GOTO 550Existem vários casos de FOR "abandonados" através de GOTOs e RETURNs no código original. Em alguns casos foi possível usar o BREAK em outros eu substituí o FOR X=0 TO N / NEXT X por X=0 / X=X+1 : IF X <= N THEN GOTO xxx ENDIF.
Apesar de todo o trabalho, parece que o programa está funcionando. Você pode baixá-lo do github..
Nenhum comentário:
Postar um comentário