Piedra, papel, tijeras
Descripción del contenido de la página
Juego "Piedra, papel, tijeras" escrito en Forth, para jugar contra la máquina.
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