Piedra, papel, tijeras

Descripción del contenido de la página

Juego "Piedra, papel, tijeras" escrito en Forth, para jugar contra la máquina.

Etiquetas:

Entre las muchas cosas importantes pendientes de hacerse en el mundo en un par de tardes de invierno está escribir un jueguecito de computadora. ¿Uno de esos en cuatro dimensiones o más, con millones de colorines y sonido cuadrafónico, cuyo argumento es matar todo lo que se mueva alrededor? No, eso está muy visto, no tiene mérito. Además, sólo los gráficos supondrían un desperdicio de megaoctetos.

Suelo hojear a menudo los diez volúmenes de mi computer, la estupenda enciclopedia de los 1980, versión española de Home Computer Course y Home Computer Advanced Course. Sus páginas, a pesar del paso del tiempo, son fuente inagotable de ideas, de conocimientos y de inspiración.

En el volumen 8, página 1760, está el listado de un sencillo programa en BASIC para jugar contra la máquina al popular juego de manos «Piedra, papel, tijeras». Fue escrito por Peter Shaw para la computadora Oric (para la Oric Atmos, no para la Oric 1, lo que se deduce del uso de los nuevos comandos de la Atmos que hacían efectos de sonido).

Como me suele ocurrir, enseguida pensé: Reescribir esto en Forth sería muy entretenido, quedaría más elegante e incluso parecería poesía.

Código fuente

La prosa de la versión original en BASIC

Para quien dude de que el BASIC es pesada y farragosa prosa y no entienda por qué el Forth es grácil y elegante poesía, a continuación transcribo el listado del programa de Peter Shaw que me sirvió de inspiración, para poder compararlo. (Corrijo una errata que había en la línea 250).

Antes de eso, para quien no conozca el juego «Piedra, papel, tijeras», cito las instrucciones que acompañaban el listado:

Tradicionalmente este juego se practica con las manos. Los dos jugadores, con sus manos a la espalda, deben mostrarlas simultáneamente imitando con ellas el objeto escogido. Deben elegir entre piedra, papel y tijeras. Las tijeras cortan el papel, la piedra rompe las tijeras, el papel cubre la piedra. Una vez hecha la elección, pulse C para tijeras, pulse R para piedra, pulse P para papel. Gana el jugador que totalice diez puntos.
 10 REM PIEDRA, PAPEL, TIJERAS
 20 CLS**PETER SHAW**
 30 PAPER 0:INK 3
 40 A=INT(RND(1)*2):PING
 50 PLOT 12,2,"PIEDRA-PAPEL-TIJERAS"
 55 PLOT 6,4,"HUMANO "+STR$(HS)
 56 PLOT 29,4,"YO "+STR$(OS)
 60 GET A$:ZAP:FOR P=0 TO 7:INK P:WAIT 4:NEXT P
 65 CLS
 70 IF A$="R" THEN V=0
 80 IF A$="P" THEN V=1
 90 IF A$="C" THEN V=2
100 PRINT:PRINT:PRINT:PRINT:PRINT:PRINT:PRINT
110 PRINT "YO TENGO ";
120 PRINT IF A=0 THEN PRINT "PIEDRA"
130 PRINT IF A=1 THEN PRINT "PAPEL"
140 PRINT IF A=2 THEN PRINT "TIJERAS"
150 PRINT:PRINT:PRINT
160 PRINT "TU TIENES ";
170 PRINT IF V=0 THEN PRINT "PIEDRA"
180 PRINT IF V=1 THEN PRINT "PAPEL"
190 PRINT IF V=2 THEN PRINT "TIJERAS"
200 PRINT:PRINT:PRINT:SHOOT
210 IF V=A THEN PRINT "EMPATE"
220 IF V=0 AND A=1 THEN PRINT "PAPEL CUBRE PIEDRA. YO GANO":OS=OS+1
230 IF V=0 AND A=2 THEN PRINT "PIEDRA ROMPE TIJERAS. TU GANAS":HS=HS+1
240 IF V=1 AND A=0 THEN PRINT "PAPEL CUBRE PIEDRA. TU GANAS":HS=HS+1
250 IF V=1 AND A=2 THEN PRINT "TIJERAS CORTAN PAPEL. YO GANO":OS=OS+1
260 IF V=2 AND A=0 THEN PRINT "PIEDRA ROMPE TIJERAS. YO GANO":OS=OS+1
270 IF V=2 AND A=1 THEN PRINT "TIJERAS CORTAN PAPEL. TU GANAS":HS=HS+1
280 PLOT 13,32,"PULSA UNA TECLA"
290 EXPLODE:WAIT 30
300 GOTO 30
310 CLS
320 IF HS=10 THEN PING:PRINT "BRAVO. TU GANAS"
330 IF OS=10 THEN ZAP:PRINT "YO GANO OTRA VEZ"
340 PRINT:PRINT:PRINT
345 WAIT 20:EXPLODE
350 END

La poesía de mi versión en Forth

Una vez vista la prosa, veamos la poesía. Mi versión no tiene sonidos ni falta que le hacen; y las teclas de manejo las he cambiado por 1, 2 y 3, por un lado porque son más cómodas, pues están contiguas, y por otro porque simplifican algunos cálculos y algoritmos.

\ ppt.fs

\ Piedra, papel, tijeras

\ Copyright (C) 2010,2012 Marcos Cruz (programandala.net)
\ Licencia/Permesilo/License:
\ http://programandala.net/license

\ Written in ANS Forth
\ Tested with Gforth and Forth 5mx

\ Inspired by a program written in BASIC
\ by Peter Shaw for the Oric Atmos computer,
\ published in "Home Computer Course"
\ (volume 8, page 1760 of its Spanish version,
\ called "mi computer").

\ History
\ 2010-01-16 First draft for Forth 5mx.
\ 2010-01-17 Finished. Works also under Gforth (source in utf-8 encoding).
\ 2012-03-30 Some formatting in the source code.

forth [defined] environment  [if]
  environment  \ wordlist used by some Forth systems to keep the environment queries
[then]
[defined] gforth constant gforth?
[defined] forth5mx constant forth5mx?  \ my own Forth system

only forth
[defined] vocabulary  [if]
vocabulary ppt  also ppt
[then]  definitions  decimal

[undefined] d=  [if]
: d=  ( d1 d2 -- f )
  rot = >r = r> and
  ;
[THEN]

gforth? [undefined] random and  [if]
  include random.fs  \ Gforth standard extension
[then]
forth5mx? [if]
  ' rnd alias random
[then]

1 constant stone
2 constant paper
3 constant scissors
10 constant max-score
variable human-choice
variable human-score
variable computer-choice
variable computer-score

: .title  ( -- )
  ." Piedra, papel, tijeras"
  ;

: .run  ( -- )
  ." Escribe RUN para jugar."
  ;

: pause  ( -- )
  key drop
  ;

: any-key  ( -- )
  cr ." Pulsa una tecla para continuar." pause
  ;

: .scores  ( -- )
  ." Tu puntuación: " human-score @ .
  cr ." Mi puntuación: " computer-score @ .
  ;

: .choice  ( u -- )
  case
    stone of ." piedra" endof
    paper of ." papel" endof
    scissors of ." tijeras" endof
  endcase
  [char] . emit
  ;

: .about  ( -- )
  cr ." Copyright (C) 2010,2012 Marcos Cruz (programandala.net)"
  cr ." Licencia/Permesilo/License:"
  cr ." http://programandala.net/licencia"
  cr
  cr ." Inspirado en un programa escrito en BASIC"
  cr ." por Peter Shaw para la computadora Oric Atmos,"
  cr ." publicado en la enciclopedia"
  cr ." 'mi computer', volumen 8, página 1760."
  ;

: init  ( -- )
  page .title cr .about cr
  0 human-score !
  0 computer-score !
  ;

: computer  ( -- u )
  3 random 1+
  ;

: valid-key?  ( c -- f )
  dup [char] 0 >
  swap [char] 4 < and
  ;

: human-key  ( -- c )
  0
  begin
    drop key dup valid-key?
  until
  ;

: .human-option  ( u -- )
  dup . ." = " .choice
  ;

: .human-options  ( -- )
  ." Es tu turno. Elige:" cr
  cr stone .human-option
  cr paper .human-option
  cr scissors .human-option
  ;

: human-option  ( -- u )
  human-key [char] 0 -
  ;

: human  ( -- u)
  .human-options human-option
  ;

: choices  ( -- u1 u2 )
  computer-choice @
  human-choice @
  ;

: .computer-choice  ( -- )
  ." Yo tengo " computer-choice @ .choice
  ;

: .human-choice  ( -- )
  ." Tú tienes " human-choice @ .choice
  ;

: .choices  ( -- )
  .computer-choice cr .human-choice
  ;

: computer-wins-round?  ( -- f )
  choices stone scissors d=
  choices scissors paper d= or
  choices paper stone d= or
  ;

: human-wins-game?  ( -- f )
  human-score @ max-score =
  ;

: computer-wins-game?  ( -- f )
  computer-score @ max-score =
  ;

: game-over?  ( -- f )
  human-wins-game? computer-wins-game? or
  ;

: i-win-round  ( -- )
  ." Yo gano."  1 computer-score +!
  ;

: you-win-round ( -- )
  ." Tú ganas."  1 human-score +!
  ;

: combined  ( u1 u2 -- u3 )
  2dup min 16 * >r max r> +
  ;

: tie?  ( -- f )
  choices =
  ;

: choices-combination ( -- true | u )
  tie? ?dup 0=
  if  choices combined  then
  ;

: .explanation ( -- )
  choices-combination
  case
    true of ." Empate." endof
    stone paper combined of ." El papel envuelve la piedra." endof
    stone scissors combined of ." La piedra rompe las tijeras." endof
    paper scissors combined of ." Las tijeras cortan el papel." endof
  endcase
  ;

: .round-winner  ( -- )
  tie? 0=
  if
    computer-wins-round?
    if  i-win-round
    else  you-win-round
    then
  then
  ;

: result  ( -- )
  page .choices
  cr cr .explanation
  space .round-winner
  cr cr .scores
  cr any-key
  ;

: .game-winner  ( -- )
  human-wins-game?
  if  ." Has"
  else  ." He"
  then  ."  ganado la partida."
  ;

: game-over  ( -- )
  page .game-winner
  cr cr .scores
  cr cr .run
  ;

: round  ( -- )
  page
  computer computer-choice !
  human human-choice !
  result
  ;

: run  ( -- )
  init any-key
  begin
    round  game-over?
  until
  game-over
  ;

cr cr .title
cr cr .run

Descargas