#!/bin/bash
# Skrypt aceydeucey odkrywający dwie karty. Twoim zadaniem jest
# zgadnięcie, czy trzecia karta będzie mieściła się w zakresie określonym
# przez dwie pierwsze. Jeżeli na przykład będą to karty 6 i 8, to
# karta 7 mieści się w zakresie, a 9 nie mieści się.

function initializeDeck
{
  # Na początku tworzona jest talia kart.

  card=1
  while [ $card != 53 ]     # Talia składa się z 52 kart, to wiesz?
  do
    deck[$card]=$card
    card=$(( $card + 1 ))
  done
}

function shuffleDeck
{
  # Nie jest to prawdziwe tasowanie, tylko losowe wybieranie wartości
  # z tabeli 'deck' (talia) i umieszczanie w "potasowanej" tabeli
  # 'newdeck' (nowa talia).

  count=1

  while [ $count != 53 ]
  do
    pickCard
    newdeck[$count]=$picked
    count=$(( $count + 1 ))
  done
}

function pickCard
{
  # To jest najbardziej interesująca funkcja wybierająca losowo kartę z talii.
  # W celu znalezienia dostępnej karty funkcja korzysta z tabeli 'deck'.

  local errcount randomcard

  threshold=10       # Maksymalna liczba prób wylosowania karty.
  errcount=0

  # Losowe wybranie karty, która nie została wcześniej wybrana z talii.
  # Liczba prób jest zapisana w zmiennej threshold (próg), po przekroczeniu
  # następuje przerwanie operacji (zapobiega się w ten sposób nieskończonemu
  # wykonywaniu pętli w celu znalezienia karty, która nie została jeszcze
  # wybrana).

  while [ $errcount -lt $threshold ]
  do
    randomcard=$(( ( $RANDOM % 52 ) + 1 ))
    errcount=$(( $errcount + 1 ))

    if [ "${deck[$randomcard]}" != "0" ] ; then
      picked=${deck[$randomcard]}
      deck[$picked]=0   # Karta wybrana, zwalniamy miejsce.
      return $picked 
    fi
  done

  # Jeżeli wykonywany jest ten kod, oznacza to, że nie można było
  # wylosować karty. Dlatego trzeba z tabeli wybrać pierwszą dostępną
  # kartę.

  randomcard=1

  while [ ${newdeck[$randomcard]} -eq 0 ]
  do
    randomcard=$(( $randomcard + 1 ))
  done

  picked=$randomcard
  deck[$picked]=0      # Karta wybrana, zwalniamy miejsce.

  return $picked
}

function showCard
{
  # Ta funkcja wykorzystuje operacje div i mod do określenia
  # koloru i wartości karty, choć w tej grze ważna jest tylko wartość.
  # Niemniej jednak wygląd też się liczy, a powyższe polecenia
  # ułatwiają realizację zadania.

  card=$1

  if [ $card -lt 1 -o $card -gt 52 ] ; then
    echo "Błędna wartość karty: $card."
    exit 1
  fi

  # Operacje div i mod. Nauka matematyki w szkole nie poszła na marne!

  suit="$(( ( ( $card - 1) / 13 ) + 1))"
  rank="$(( $card % 13))"

  case $suit in
    1 ) suit="kier"   ;;
    2 ) suit="trefl"  ;;
    3 ) suit="pik"    ;;
    4 ) suit="karo"   ;;
    * ) echo "Błędny kolor karty: $suit"; exit 1
  esac 

  case $rank in 
    0 ) rank="król"   ;;
    1 ) rank="as"     ;;
    11) rank="walet"  ;;
    12) rank="dama"   ;;
  esac

  cardname="$rank $suit"
}

function dealCards 
{
  # W Acey Deucey odkrywane są dwie karty...

  card1=${newdeck[1]}      # Ponieważ talia jest przetasowana,
  card2=${newdeck[2]}      # odkrywamy dwie pierwsze karty,
  card3=${newdeck[3]}      # a trzecią odkładamy bez odkrywania.

  rank1=$(( ${newdeck[1]} % 13 ))   # Określenie wartości kart
  rank2=$(( ${newdeck[2]} % 13 ))   # w celu uproszczenia późniejszych
  rank3=$(( ${newdeck[3]} % 13 ))   # obliczeń.

  # Poprawka dla króla, którego domyślna wartość jest równa 0, a powinna być 13.
  
  if [ $rank1 -eq 0 ] ; then
    rank1=13;
  fi
  if [ $rank2 -eq 0 ] ; then
    rank2=13;
  fi
  if [ $rank3 -eq 0 ] ; then
    rank3=13;
  fi

  # Teraz porządkujemy karty, aby ta o mniejszej wartości była pierwsza.

  if [ $rank1 -gt $rank2 ] ; then
    temp=$card1; card1=$card2; card2=$temp
    temp=$rank1; rank1=$rank2; rank2=$temp
  fi

  showCard $card1 ; cardname1=$cardname
  showCard $card2 ; cardname2=$cardname

  showCard $card3 ; cardname3=$cardname    # Trzeciej karty na razie nie odkrywamy.

  echo "Odkryłem karty:" ; echo "   $cardname1" ; echo "   $cardname2"
}

function introblurb
{
cat << EOF

Witaj w Acey Deucey. Twoim zadaniem jest odgadnięcie, czy trzecia wybrana karta
mieści się w przedziale wartości określonym przez dwie pierwsze karty wybrane z talii.
Jeżeli na przykład odkryję 5 kier i waleta karo, musisz odgadnąć, czy trzecia karta
będzie miała wartość większą niż 5 oraz mniejszą niż walet (tj. 6, 7, 8, 9 lub 10
dowolnego koloru).

Gotowy? Zaczynamy!

EOF
}

#################################################################
####  Główna część kodu

games=0
won=0

if [ $# -gt 0 ] ; then    # Wyświetlenie informacji, jeżeli podany został argument.
  introblurb
fi

while [ /bin/true ] ; do
  # Tu zaczyna się główny kod.

  initializeDeck
  shuffleDeck
  dealCards

  splitValue=$(( $rank2 - $rank1 ))

  if [ $splitValue -eq 0 ] ; then
    echo "Nie zgaduj, ponieważ obie karty mają taką samą wartość!"
    continue
  fi

  echo -n "Różnica wartości wynosi $splitValue. Jak myślisz, czy wartość "
  echo -n "trzeciej karty mieści się w przedziale (t/n/k)? "
  read answer

  if [ "$answer" = "k" ] ; then
    echo ""
    echo "Liczba rozdań: $games, z czego wygranych: $won."
    exit 0
  fi

  echo "Trzecia karta: $cardname3."
 
  # Czy wartość karty mieści się w zadanym przedziale? Sprawdźmy to.
  # Pamiętaj, że wartość równa granicznej oznacza, że karta się nie mieści.

  if [ $rank3 -gt $rank1 -a $rank3 -lt $rank2 ] ; then # Wygrałeś!
    winner=1
  else
    winner=0
  fi
  
  if [ $winner -eq 1 -a "$answer" = "t" ] ; then
    echo -n "Obstawiłeś, że trzecia karta mieści się w przedziale, "
    echo "i rzeczywiście tak jest. Wygrałeś!"
    won=$(( $won + 1 ))
  elif [ $winner -eq 0 -a "$answer" = "n" ] ; then
    echo -n "Obstawiłeś, że trzecia karta nie mieści się w przedziale, "
    echo "i rzeczywiście tak jest. Wygrałeś!"
    won=$(( $won + 1 ))
  else
    echo "Przyjąłeś złą strategię. Przegrałeś."
  fi

  games=$(( $games + 1 ))    # Ile było rozdań?
done

exit 0
