Rebol3 Code Examplex
Go Fish
Implement the card game rules for Go Fish.
Rebol [
title: "Rosetta code: Go Fish"
file: %Go_fish.r3
url: https://rosettacode.org/wiki/Go_Fish
]
go-fish-game: function/with [
"Play a game of Go Fish"
][
deck: fisher-yates-shuffle copy ordered-deck
clear ai-hand clear ai-book-list clear ai-guess
clear my-hand clear my-book-list
ai-books: my-books: 0
deal-cards/ai 9 ai-hand
deal-cards 9 my-hand
message: clear ""
draw-screen
while [ai-books + my-books < 13][
computer-turn
if ai-books + my-books < 13 [player-turn]
]
clear-screen
draw-screen
print ""
print as-yellow "GAME OVER"
print ["^/Computer books:" as-red pad ai-books -3
"^/Player books:" as-green pad my-books -3]
][
;; Build deck
ordered-deck: []
foreach r ranks: "A23456789TJQK" [
foreach s "♣♦♥♠" [
append ordered-deck ajoin [r s]
]
]
;; Charsets used to filter key inputs
player-card-keys: charset join ranks "x"
player-yes-no: charset "ynx"
;; Game states
ai-hand: [] ai-book-list: [] ai-guess: []
my-hand: [] my-book-list: []
deck: []
ai-books: my-books: 0
message: ""
;; Shuffle function
fisher-yates-shuffle: func [list [block!] /local len j] [
len: length? list
repeat i len [
j: i + random (len - i)
swap at list i at list j
]
list
]
;; Cards sorting
rank-modifiers: #[
#"A" 130 #"K" 120 #"Q" 110 #"J" 100 #"T" 90
#"9" 80 #"8" 70 #"7" 60 #"6" 50 #"5" 40
#"4" 30 #"3" 20 #"2" 10
]
card-rank: func [card] [rank-modifiers/(card/1)]
sort-hand: func [hand] [
sort/compare hand func [a b] [
(card-rank a) < (card-rank b)
]
]
;; Screen output
clear-screen: does [prin "^[[2J^[[H"]
draw-screen: does [
clear-screen
;; title bar
print as-yellow "=================================="
print as-yellow " G O F I S H "
print as-yellow "=================================="
print ""
;; deck count
print ajoin [as-cyan " Deck: " length? deck " cards remaining"]
print ""
;; books lines
print ajoin [as-red " Computer books: " pad ai-books -2 " [ " ai-book-list " ]"]
print ajoin [as-green " Your books: " pad my-books -2 " [ " my-book-list " ]"]
print as-yellow "----------------------------------"
print ""
;; my hand
print [as-cyan "Your hand:" as-yellow sort-hand my-hand]
print ""
;; last message
unless empty? message [ print message ]
print as-yellow "----------------------------------"
]
status: func[txt][
if block? txt [txt: ajoin txt]
append append message txt LF
]
;; Game functions
deal-cards: function [num hand /ai] [
new: take/part deck num
unless ai [
status ["You draw new card" if num > 1 ["s"] ": " new]
]
append hand new
]
find-in: func [hand kind [char!]] [
forall hand [
if hand/1/1 = kind [return kind]
]
none
]
guess-from: function [hand guessed] [
kind: first random/only exclude hand guessed
append guessed kind
kind
]
check-for-books: func [hand /ai /local kind n count] [
if empty? hand [exit]
sort hand
kind: hand/1/1 n: count: 0
while [not tail? hand][
either kind = hand/1/1 [
n: n + 1
if n = 4 [
remove/part next hand -4
++ count
append either ai [ai-book-list][my-book-list] kind
if tail? hand [break]
kind: hand/1/1 n: 0
continue
]
][
kind: hand/1/1
n: 1
]
++ hand
]
either ai [
ai-books: ai-books + count
][ my-books: my-books + count]
if count > 0 [
status ["New " as-green count " book" if count > 1 "s" " collected!"]
]
count
]
transfer-cards: func [
;; Move all cards of a given rank from src to trg
src [block!] trg [block!] kind [char!]
][
while [not tail? src] [
either kind = src/1/1 [append trg take src][++ src]
]
]
computer-turn: func [/local kind a] [
forever [
if empty? ai-hand [
if empty? deck [exit]
deal-cards/ai 3 ai-hand
]
ai-guess: unique ai-guess
kind: guess-from ai-hand ai-guess
draw-screen
print as-red { -------------------^/ - COMPUTER TURN -^/ -------------------}
clear message
prin ajoin [" Do you have any " as-green kind "s? "]
a: wait-for-key/only player-yes-no
if any [none? a a = #"x"][ halt ]
either a = #"y" [
transfer-cards my-hand ai-hand kind
status ["Computer took your " as-green kind "s!"]
check-for-books/ai ai-hand
draw-screen
][
status ["Go Fish! Computer draws a card."]
deal-cards/ai 1 ai-hand
check-for-books/ai ai-hand
draw-screen
exit
]
]
]
player-turn: func [/local kind n] [
forever [
if empty? my-hand [
if empty? deck [exit]
deal-cards 3 my-hand
]
draw-screen
print as-green { -------------------^/ - PLAYER TURN -^/ -------------------}
clear message
prin " Your guess: "
kind: wait-for-key/only player-card-keys
if any [none? kind kind = #"x"][ halt ]
kind: uppercase kind
unless find-in my-hand kind [
status as-red "You must hold that rank to ask for it!"
draw-screen
exit
]
either find-in ai-hand kind [
transfer-cards ai-hand my-hand kind
status ["You took the computer's " as-green kind "s!"]
check-for-books my-hand
draw-screen
][
status ["Computer don't have any " as-green kind "s!"]
deal-cards 1 my-hand
check-for-books my-hand
draw-screen
exit
]
]
]
]
;--- Main ---
go-fish-game