Go Fish/Wren

From Rosetta Code
Revision as of 11:23, 30 July 2021 by PureFox (talk | contribs) (Put final brace on its own line.)
Translation of: Kotlin
Library: Wren-dynamic
Library: Wren-trait
Library: Wren-seq
Library: Wren-sort
Library: Wren-ioutil
Library: Wren-str

<lang ecmascript>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)

}</lang>