I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Go Fish/Wren

From Rosetta Code
Translation of: Kotlin
Library: Wren-dynamic
Library: Wren-trait
Library: Wren-seq
Library: Wren-sort
Library: Wren-ioutil
Library: Wren-str
import "random" for Random
import "/dynamic" for Enum
import "/trait" for Comparable, Stepped
import "/seq" for Lst
import "/sort" for Sort
import "/ioutil" for Input
import "/str" for Str
 
var FACES = "23456789tjqka"
var SUITS = "cdhs"
 
var Turn = Enum.create("Turn", ["user", "comp"])
 
class Card is Comparable {
construct new(face, suit) {
_face = face
_suit = suit
_value = FACES.indexOf(face) * 4 + SUITS.indexOf(suit)
}
 
face { _face }
suit { _suit }
value { _value }
 
compare(other) { (_value - other.value).sign }
 
toString { "%(face)%(suit)" }
}
 
var r = Random.new()
 
var ranks = [
"twos", "threes", "fours", "fives", "sixes", "sevens", "eights",
"nines", "tens", "jacks", "queens", "kings", "aces"
]
 
var deck = []
var userHand = []
var userBooks = []
var compHand = []
var compBooks = []
var compPrev = []
 
var turn = Turn.user // user always starts
 
var createDeck = Fn.new {
for (suit in SUITS) {
for (face in FACES) deck.add(Card.new(face, suit))
}
}
 
var shuffleDeck = Fn.new { r.shuffle(deck) }
 
/* Chooses a rank at random provided it hasn't already been chosen
during the current turn. If all ranks have already been chosen,
it chooses the first again. */

var compSelectRankIndex = Fn.new {
var choices = Lst.distinct(compHand.map { |c| c.face }.toList).
where { |f| !compPrev.contains(f) }.toList
var size = choices.count
var choice = (size == 0) ? compHand[0].face : choices[r.int(size)]
return FACES.indexOf(choice)
}
 
var userChoices = Fn.new { Lst.distinct(userHand.map { |c| c.face }.toList) }
 
var printHand = Fn.new { System.print("Your cards : %(userHand.join(" "))") }
 
var printBooks = Fn.new {
System.print("Your books : %(userBooks.join(" "))")
System.print("My books  : %(compBooks.join(" "))")
}
 
var printTurn = Fn.new {
System.print( (turn == Turn.user) ? "--- YOUR TURN ---" : "--- MY TURN ---")
}
 
var checkForBooks = Fn.new { |hand, books|
var newBooks = Lst.groupBy(hand) { |c| c.face }.toList.
where { |me| me.value.count == 4 }.
map { |me| me.key }.toList
if (newBooks.count > 0) {
books.addAll(newBooks)
var cmp = Fn.new { |c1, c2| (FACES.indexOf(c1) - FACES.indexOf(c2)).sign }
Sort.insertion(books, cmp)
for (b in newBooks) {
for (i in hand.count-1..0) {
if (hand[i].face == b) hand.removeAt(i)
}
}
if (hand.count == 0 && deck.count > 0) {
var e = deck.removeAt(0)
if (hand == userHand) System.print("You drew : %(e)")
hand.add(e)
}
System.print("Added %(newBooks.join(" ")) to books")
}
}
 
var showStateOfPlay = Fn.new { |showTurn|
System.print()
Sort.quick(userHand)
printHand.call()
printBooks.call()
if (showTurn) printTurn.call()
System.print()
}
 
// create and shuffle deck and deal cards
createDeck.call()
shuffleDeck.call()
for (i in Stepped.new(0..16, 2)) userHand.add(deck[i])
for (i in Stepped.new(1..17, 2)) compHand.add(deck[i])
for (i in 0..17) deck.removeAt(0)
 
// check if there are any books in initial hands
checkForBooks.call(userHand, userBooks)
checkForBooks.call(compHand, compBooks)
showStateOfPlay.call(true)
 
while (true) {
while (true) {
var rank
if (turn == Turn.user) {
while (true) {
rank = Str.lower(Input.txtOpt("Enter the rank you want : ", ranks))
var choice = FACES[ranks.indexOf(rank)]
if (userChoices.call().contains(choice)) break
System.print("Your hand does not contain that rank, try again.")
}
} else {
var r = compSelectRankIndex.call()
rank = ranks[r]
System.print("The rank I want is : %(rank)")
compPrev.add(FACES[r])
}
var face = FACES[ranks.indexOf(rank)]
var matches = 0
if (turn == Turn.user) {
for (i in compHand.count-1..0) {
if (compHand[i].face == face) {
matches = matches + 1
userHand.add(compHand.removeAt(i))
}
}
System.print("Matches : %(matches)")
if ((matches == 0 || userHand.count == 0) && deck.count > 0) {
var e = deck.removeAt(0)
System.print("You drew : %(e)")
userHand.add(e)
}
checkForBooks.call(userHand, userBooks)
if (userBooks.count >= 7) {
showStateOfPlay.call(false)
System.print("Congratulations, you've won!")
return
}
} else {
for (i in userHand.count-1..0) {
if (userHand[i].face == face) {
matches = matches + 1
compHand.add(userHand.removeAt(i))
}
}
System.print("Matches: %(matches)")
if ((matches == 0 || compHand.count == 0) && deck.count > 0) {
var e = deck.removeAt(0)
compHand.add(e)
}
checkForBooks.call(compHand, compBooks)
if (compBooks.count >= 7) {
showStateOfPlay.call(false)
System.print("Commiserations, but I've won!")
return
}
}
if (matches > 0) showStateOfPlay.call(true) else break
}
turn = (turn == Turn.user || userHand.count == 0) ? Turn.comp : Turn.user
if (turn == Turn.comp) compPrev.clear()
showStateOfPlay.call(true)
}