Sections

2019-12-06

Oko bere (Czech Twenty-One/Blackjack Variant) in R

# Oko bere (The Eye Takes It) belongs to a family of Twenty-One-like games, where you draw cards assigned different values from a randomized deck with the objective to come as close as possible to but not exceed a certain number of points, typically 21. There also exist special hands. The most popular variant is Blackjack. This implementation plays mostly like Blackjack, but you can't split as I didn't implement multiplayer, the card deck is German (called Mariášové karty in Czechia, Mariáš is a game similar to Hearts in Windows), the royal cards are worth 1,2,3,11 points, and the special hand is Velke oko (Great Eye) of 2 Aces (normally over).

promptInt = function(promptString, defaultValue){
  # this is do-while
  repeat{
    userInputRaw = readline(promptString)
    if(userInputRaw == ""){
      return(defaultValue)
    }
    userInput = as.integer(userInputRaw)
    if(!is.na(userInput)){
      break
    }
    cat(userInputRaw, "couldn't be read as an integer!")
  }
  return(userInput)
}

ranksMarias = c("VII", "VIII", "IX", "X", "Knave", "Vamp", "King", "Ace")
suitsMarias = c("Acorns", "Bells", "Hearts", "Leaves")
cardsMarias = length(ranksMarias)*length(suitsMarias) # 32
ranksPoker = c("A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K")
suitsPoker = c("Clubs", "Diamonds", "Hearts", "Spades")
cardsPoker = length(ranksPoker)*length(suitsPoker) # 52

newDeck = function(){
  set.seed(as.integer(Sys.time()))
  cardlist = sample(0:(cardsMarias-1), 32, replace = FALSE)
  deck = NULL
  i = 0
  while(i <= cardsMarias){
    deck[[i+1]] = c(ranksMarias[cardlist[i+1]%%length(ranksMarias)+1], suitsMarias[cardlist[i+1]%/%length(ranksMarias)+1])
    i = i + 1
  }
  #print(deck)
  return(deck)
}

# Oko bere hybridized with Black Jack
cardValues = c(7,8,9,10,1,2,3,11)
money = 100
housemoney = 100
deck = NULL
repeat{ # game
  cat("You have", money, "coins, computer has", housemoney, "coins.\n")
  bet = promptInt("Place your bet, default 10, 0 to quit: ", 10)
  if(bet == 0){
    break
  }
  deck = newDeck()
  scorePlayer = 0
  scoreComputer = 0
  playerStands = FALSE
  computerStands = FALSE
  playerAces = 0 # Velke Oko
  computerAces = 0
  surrendered = FALSE
  doubled = FALSE

  repeat{ # turn
    # Player
    if(!playerStands){
      curcard = head(deck, 1)
      if(is.na(curcard[[1]][1])){ # that can also happen
        cat("The deck has run out!")
        break
      }
      deck = tail(deck, length(deck)-1)
      if(curcard[[1]][1] == "Ace"){ # Velke Oko
        playerAces = playerAces + 1
      }
      scorePlayer = scorePlayer + cardValues[match(curcard[[1]][1], ranksMarias)]
      cat("You drew", curcard[[1]][1], "of", curcard[[1]][2], "so your score is now", scorePlayer, "points.\n")
      if(scorePlayer == 22 && playerAces == 2){
        cat("You got Velke Oko!")
      }
    }
    if(doubled){
      playerStands = TRUE
    }

    # Computer - plays like dealer in Black Jack
    if(!computerStands && scoreComputer < 17){ # be more careful
      curcard = head(deck, 1)
      if(is.na(curcard[[1]][1])){
        cat("The deck has run out!")
        break
      }
      deck = tail(deck, length(deck)-1)
      if(curcard[[1]][1] == "Ace"){ # Velke Oko
        computerAces = computerAces + 1
      }
      scoreComputer = scoreComputer + cardValues[match(curcard[[1]][1], ranksMarias)]
      cat("Computer drew", curcard[[1]][1], "of", curcard[[1]][2], "so its score is now", scoreComputer, "points.\n")
      if(scoreComputer == 22 && computerAces == 2){
        cat("Computer got Velke Oko!")
      }
    }else{
      computerStands = TRUE
    }

    if(!playerStands){ # cannot implement split, refactoring needed
      wantnext = readline("(H)it, (s)tand, (d)ouble, or s(u)rrender? ")
      if (wantnext == "s" || wantnext == "S"){
        playerStands = TRUE
      }
      if (wantnext == "d" || wantnext == "D"){
        bet = bet * 2
        doubled = TRUE
        cat("You doubled the bet to", bet, "coins, promising to take 1 last hit.\n")
      }
      if (wantnext == "u" || wantnext == "u"){
        surrendered = TRUE
        break
      }
    }
    if(computerStands && playerStands){
      break
    }
  }

  # evaluation (exceedingly crappy code)
  if(surrendered){
    cat("You have surrendered, losing half the bet, which is", bet/2, "coins.\n")
    money = money - bet/2
    housemoney = housemoney + bet/2
  }else{ # Velke Oko - 2 Aces
    if(scorePlayer == 22 && playerAces == 2){
      if(scoreComputer == 22 && computerAces == 2){
        cat("Tie, you both have Velke Oko.")
      }
      cat("You won over computer with Velke Oko.\n")
      money = money + bet
      housemoney = housemoney - bet
    }else if(scoreComputer == 22 && computerAces == 2){
      cat("Computer won over you with Velke Oko.\n")
      money = money - bet
      housemoney = housemoney + bet
    }else{ # Other cases
      if(scorePlayer > 21){ # if both are over, player still loses
        cat("You are over, you lose anyway.\n")
        money = money - bet
        housemoney = housemoney + bet
      }else if(scoreComputer > 21){
        cat("Computer is over, it loses.\n")
        money = money + bet
        housemoney = housemoney - bet
      }else if(scorePlayer > scoreComputer){
        cat("You won over computer.\n")
        money = money + bet
        housemoney = housemoney - bet
      }else if(scorePlayer < scoreComputer){
        cat("Computer won over you.\n")
        money = money - bet
        housemoney = housemoney + bet
      }else{
        cat("Tie, no one loses or gains anything.\n")
      }
    }
  }

  if(money < 0){
    cat("You've gone bankrupt.")
    break
  }
  if(housemoney < 0){
    cat("Computer has gone bankrupt.")
    break
  }
}

# I also wrote a lottery game in Python some years ago. These beginner programs are way better than all those lootboxes in AAA games.

No comments:

Post a Comment

Barely anyone comments, so I don't moderate. Free advertising, I guess.