There are many CodeProject articles about other card games, but nothing with Schafkopf. So I started to create this document. I will not describe and explain every detail of the complete demo project, but how to use it and play the game.

Download Schafkopf.zip

## Introduction

This article and the demo are about getting started using my `SchafkopfStarterKit`

VB.NET project.

Version **2.6** or higher includes source code for **C#** in `CSchafkopfStarterKit`

project.` `

## Background

There are many CodeProject articles about other card games, but nothing with `Schafkopf`

. So I started to create this document.

I will not describe and explain every detail of the complete demo project but how to use it and play the game.

## Using the Code

#### Here is a Quick Overview

#### MainWindow Concept and Code

When you start the program, the main window shows a complete deck of cards as a card fan and renders it in a circular panel (based on the above mentioned CodeProject article, **Power of Templates in Control Development Within Windows Presentation Foundation** including this credit: „I took this panel from the color swatch sample that ships with Microsoft Expression Blend“).

On top of the window, there are some menu items – click on **1. New Game** please, then you should see something like that:

`MainWindow`

has the following controls:

- A
`Grid`

with
- a
`StackPanel`

called `MyPanel`

- a
`WrapPanel`

(on top) with the menu items

`HistoryTextBox`

for Trick History - Panels for the cards within the
`StackPanel`

called `MyPanel`

`DockPanel`

`Panel0`

on top for `player0 = North`

`DockPanel`

`Panel2`

on bottom for `player2 = South`

`WrapPanel`

`Panel1`

on right side for `player1 = East`

`WrapPanel`

`Panel3`

on left side for `player3 = West`

`DockPanel`

`CenterPanel`

#### Card Resources and Definitions

The files in folder *Resources* are taken from** **[2].

I have changed some things as follows:

- Jacks
** **=> Unter => Under (or Sergeant) - Queens =>
** **Ober => Over (or Officer) - Diamonds => Shells or Ring
- Clubs => Acorn

To keep things easy, I left Spades (which could become „Grass“) as it was.

Class `Bridge`

is taken from** **[1].

I have changed the cards deck from 52 to 32 and adjusted the card values and colors as described above.

### Putting Things Together - WPF Concept and Code

#### Shuffle and Distribute Cards

Function `ShuffleArray`

and Function `RandomNumber`

are taken from Reference [4].

Classes `PlayingCard`

and `CircularPanel`

are taken from Reference [2].

I have added the following properties:

`Public Property CardSymbol As String`

`Public Property CardShortName As String`

`Public Property IsCallAce As Boolean`

`Public Property IsAlreadyPlayed As Boolean`

`Private Shared CardOwnerProperty As DependencyProperty = DependencyProperty.Register("CardOwner", GetType(CardOwner), GetType(PlayingCard), New PropertyMetadata(CardOwner.North))`

. . .

When you click on **1. New Game**, the `ShuffleArray`

method is started.

After that, the shuffled cards are distributed to the four `CardPanel`

s.

Public Sub NewGame()
Me.Deck.Children.Clear()
handCards0.Clear()
handCards1.Clear()
handCards2.Clear()
handCards3.Clear()
Panel0.Children.Clear()
Panel2.Children.Clear()
Panel1.Children.Clear()
Panel3.Children.Clear()
CenterPanel.Children.Clear()
cards.Clear()
iTeamDeclarer = 0
iTeamOpponent = 0
HistoryTextBox.Text = "Trick History: " & Environment.NewLine
RufAs.CardOwner = -1
bh.iCoSpieler = -1
bh.iGeber = bh.iGeber + 1
If bh.iGeber = 4 Then bh.iGeber = 0
nextMove = bh.iGeber
bh.leadPlayer = bh.iGeber
GameStatus = 2
cbxDeclarer.SelectedIndex = 4
cbxContractSuit.SelectedIndex = 8
PlayCard.IsEnabled = False
labelTrumpLead.Content = " "
labelTrumpcard.Content = "Display for Game Type"
For Each type As CardType In [Enum].GetValues(GetType(CardType))
For Each value As CardValue In [Enum].GetValues(GetType(CardValue))
Dim card As PlayingCard = New PlayingCard()
card.CardType = type
card.CardValue = value
card.Height = 135
card.Width = 85
If card.CardType = 0 Then card.CardSymbol = "Ꚛ"
If card.CardType = 1 Then card.CardSymbol = "♥"
If card.CardType = 2 Then card.CardSymbol = "♠"
If card.CardType = 3 Then card.CardSymbol = "Ⴖ"
card.CardShortName = card.CardValue
If card.CardValue = 2 Then card.CardShortName = "U"
If card.CardValue = 3 Then card.CardShortName = "O"
If card.CardValue = 4 Then card.CardShortName = "K"
If card.CardValue = 11 Then card.CardShortName = "A"
cards.Add(card)
Next
Next
cards = ShuffleArray(cards)
Dim cardShuffled As PlayingCard = New PlayingCard()
Dim i As Integer = 0
For Each cardShuffled In cards
AddHandler cardShuffled.Click, AddressOf card_Click
If i = 0 Or i = 4 Or i = 8 Or i = 12 Or i = 16 Or i = 20 Or i = 24 Or
i = 28 Then
If handCards0.Count > 0 Then
For n = 0 To handCards0.Count - 1
If handCards0.Contains(cardShuffled) = False AndAlso
cardShuffled.CardType < handCards0.Item(n).CardType Then
cardShuffled.CardOwner = CardOwner.North
If handCards0.Contains(cardShuffled) = False Then
handCards0.Insert(n, cardShuffled)
Exit For
End If
Next
If handCards0.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.North
If handCards0.Contains(cardShuffled) = False Then
handCards0.Add(cardShuffled)
Else
If handCards0.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.North
If handCards0.Contains(cardShuffled) = False Then
handCards0.Add(cardShuffled)
End If
End If
If i = 1 Or i = 5 Or i = 9 Or i = 13 Or i = 17 Or i = 21 Or i = 25 Or
i = 29 Then
If handCards2.Count > 0 Then
For n = 0 To handCards2.Count - 1
If handCards2.Contains(cardShuffled) = False AndAlso
cardShuffled.CardType < handCards2.Item(n).CardType Then
If handCards2.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.South
handCards2.Insert(n, cardShuffled)
End If
Exit For
End If
Next
If handCards2.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.South
handCards2.Add(cardShuffled)
End If
Else
If handCards2.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.South
handCards2.Add(cardShuffled)
End If
End If
End If
If i = 2 Or i = 6 Or i = 10 Or i = 14 Or i = 18 Or i = 22 Or i = 26 Or
i = 30 Then
If handCards1.Count > 0 Then
For n = 0 To handCards1.Count - 1
If handCards1.Contains(cardShuffled) = False AndAlso
cardShuffled.CardType < handCards1.Item(n).CardType Then
If handCards1.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.East
If handCards1.Contains(cardShuffled) = False Then
handCards1.Insert(n, cardShuffled)
Exit For
End If
Next
If handCards1.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.East
If handCards1.Contains(cardShuffled) = False Then
handCards1.Add(cardShuffled)
Else
If handCards1.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.East
If handCards1.Contains(cardShuffled) = False Then
handCards1.Add(cardShuffled)
End If
End If
If i = 3 Or i = 7 Or i = 11 Or i = 15 Or i = 19 Or i = 23 Or i = 27 Or
i = 31 Then
If handCards3.Count > 0 Then
For n = 0 To handCards3.Count - 1
If handCards3.Contains(cardShuffled) = False AndAlso
cardShuffled.CardType < handCards3.Item(n).CardType Then
If handCards3.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.West
If handCards3.Contains(cardShuffled) = False Then
handCards3.Insert(n, cardShuffled)
Exit For
End If
Next
If handCards3.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.West
If handCards3.Contains(cardShuffled) = False Then
handCards3.Add(cardShuffled)
Else
If handCards3.Contains(cardShuffled) = False Then
cardShuffled.CardOwner = CardOwner.West
If handCards3.Contains(cardShuffled) = False Then
handCards3.Add(cardShuffled)
End If
End If
i += 1
Next
For Each cardShuffled0 In handCards0
Panel0.Children.Add(cardShuffled0)
Next
For Each cardShuffled2 In handCards2
Panel2.Children.Add(cardShuffled2)
Next
For Each cardShuffled1 In handCards1
Panel1.Children.Add(cardShuffled1)
Next
For Each cardShuffled3 In handCards3
Panel3.Children.Add(cardShuffled3)
Next
Panel0 = SortHandCards(Panel0)
Panel1 = SortHandCards(Panel1)
Panel2 = SortHandCards(Panel2)
Panel3 = SortHandCards(Panel3)
Me.Deck.AddHandler(ToggleButton.CheckedEvent, _
New RoutedEventHandler(AddressOf OnCardSelected))
End Sub

#### Selection of the Declarer and the Game Type

The selection of the declarer and the game type are also human controlled (by the user).

You have to follow the steps as shown in the menu on top.

#### 1. New Game

A click on that menu item starts the `ShuffleArray`

method.

After that, the shuffled cards are distributed to the four `CardPanel`

s.

#### 2. Select Declarer

From the `combobox`

on the right of this label, you can select the declarer of the game (who plays a solo or calls an ace).

#### 3. **Select GameType**

From the `combobox`

on the right of this label, you can select which game type the declarer of the game wants to play – select which solo he wants to play or which ace he wants to call.

Menu item **4. Ready to Play** is only active after steps **2.** And **3. **are completed.

After you clicked it, the **Auto Play feature** moves a card to the `CenterPanel`

or - if it is the human player's turn – nothing happens until the human player clicked on one of his cards.

The label „**Waiting for Card from Player:**“ shows whose turn is next.

#### Place a Card on the CenterPanel

If it is the human player's turn, he can play one of them by clicking on one of his cards.

The clicked card is then automatically moved to the `DockPanel CenterPanel`

.

Private Sub card_Click (ByVal sender As Object, ByVal e As System.EventArgs)
Dim ACP As New AutoCardPlay
If CenterPanel.Children.Count = 4 Then
CenterPanel.Children.Clear()
HistoryTextBox.AppendText(Environment.NewLine & _
"-----------------------" &
Environment.NewLine)
End If
sender.Parent.Children.Remove(sender)
Dim cardColor As String
Dim cardValue As String
Dim cardOwner As String
If sender.CardType = 0 Then cardColor = "Ꚛ"
If sender.CardType = 1 Then cardColor = "♥"
If sender.CardType = 2 Then cardColor = "♠"
If sender.CardType = 3 Then cardColor = "Ⴖ"
cardValue = sender.CardValue
If sender.CardValue = 2 Then cardValue = "U"
If sender.CardValue = 3 Then cardValue = "O"
If sender.CardValue = 4 Then cardValue = "K"
If sender.CardValue = 11 Then cardValue = "A"
If sender.CardOwner = 0 Then cardOwner = "North"
If sender.CardOwner = 1 Then cardOwner = "East "
If sender.CardOwner = 2 Then cardOwner = "South"
If sender.CardOwner = 3 Then cardOwner = "West "
If sender.CardType = RufAs.CardType AndAlso sender.CardShortName = _
"A " Then
RufAs.IsAlreadyPlayed = True
End If
HistoryTextBox.AppendText(Environment.NewLine & cardOwner & ": " _
& cardColor &
" " & cardValue)
CenterPanel.Children.Add(CType(sender, UIElement))
System.Threading.Thread.Sleep(250)
If totalMove Mod 4 = 0 Then Trick_Content.PrevCard1 = Trick_Content.Card1
If totalMove Mod 4 = 0 Then Trick_Content.PrevCard2 = Trick_Content.Card2
If totalMove Mod 4 = 0 Then Trick_Content.PrevCard3 = Trick_Content.Card3
If totalMove Mod 4 = 0 Then
If Trick_Content.Card4 IsNot Nothing Then Trick_Content.PrevCard4 =
Trick_Content.Card4
End If
If totalMove Mod 4 = 1 Then
Trick_Content.Card1 = cardValue.ToString & " " & cardColor
Trick_Content.Card2 = Nothing
Trick_Content.Card3 = Nothing
Trick_Content.Card4 = Nothing
Trick_Content.PlayerIdCard2 = -1
Trick_Content.PlayerIdCard3 = -1
Trick_Content.PlayerIdCard3 = -1
End If
If totalMove Mod 4 = 2 Then Trick_Content.Card2 = cardValue.ToString &
" " & cardColor
If totalMove Mod 4 = 3 Then Trick_Content.Card3 = cardValue.ToString &
" " & cardColor
If totalMove Mod 4 = 0 Then Trick_Content.Card4 = cardValue.ToString &
" " & cardColor
If totalMove Mod 4 = 1 Then Trick_Content.CountCardsInTrick = 1
If totalMove Mod 4 = 2 Then Trick_Content.CountCardsInTrick = 2
If totalMove Mod 4 = 3 Then Trick_Content.CountCardsInTrick = 3
If totalMove Mod 4 = 0 Then Trick_Content.CountCardsInTrick = 4
If totalMove Mod 4 = 1 Then Trick_Content.PlayerIdCard1 = nextMove
If totalMove Mod 4 = 2 Then Trick_Content.PlayerIdCard2 = nextMove
If totalMove Mod 4 = 3 Then Trick_Content.PlayerIdCard3 = nextMove
If totalMove Mod 4 = 0 Then Trick_Content.PlayerIdCard4 = nextMove
If totalMove Mod 4 = 1 Then
tc = Trick_Content.Card1
Trick_Content.CurrentTrickWinner = nextMove
End If
If totalMove Mod 4 = 2 Then
tc = Trick_Content.Card2
Trick_Content.CurrentTrickWinner = GetCurrentTrickWinner(Me,
totalMove Mod 4)
End If
If totalMove Mod 4 = 3 Then
tc = Trick_Content.Card3
Trick_Content.CurrentTrickWinner = GetCurrentTrickWinner(Me,
totalMove Mod 4)
End If
If totalMove Mod 4 = 0 Or totalMove Mod 4 = 4 Then
tc = Trick_Content.Card4
Trick_Content.CurrentTrickWinner = GetCurrentTrickWinner(Me,
totalMove Mod 4)
End If
If totalMove Mod 4 = 1 Then
sWenz = ""
sOber = ""
If sender.CardValue = 2 Or sender.CardValue = 3 Then
If totalMove Mod 4 = 1 Then bh.leadSuit = bh.trumpCard
Else
bh.leadSuit = sender.CardType
End If
labelTrumpLead.Content = "Trump or Lead: " & bh.suitRows(bh.leadSuit)
End If
nextMove = (nextMove + 1) Mod 4
updateTurnToMoveMessage(nextMove)
If totalMove Mod 4 = 0 Then
tally()
GameStatus = GameState.FirstCardInTrick
System.Threading.Thread.Sleep(500)
Else
GameStatus = GameState.AnotherCardInTrick
End If
totalMove += 1
Trick_Content.PossibleWinnerPlayerID =
TrickWinnerID(Trick_Content.CurrentTrickWinner)
Dim cardsPanel As Object = {Panel0, Panel1, Panel2, Panel3}
For i = 0 To 3
If GameStatus.ToString = "SpielAus" Then Exit Sub
If nextMove = 2 Then
If nextMove = 2 Then Exit Sub
Else
If nextMove = i Then ACP.SelectCard(Nothing, nextMove, bh.declarer,
GameStatus, cardsPanel(nextMove), _
bh.trumpCard, Nothing, Me, bh.leadSuit)
If nextMove = i Then If i > 0 Then GameStatus = _
GameState.AnotherCardInTrick
End If
Next
End Sub

If it is the **auto player**'s turn, the `Public Sub AutoPlaceCardOnTable`

method does something similar like the `Sub card_Click`

.

At the end of this method:

ACP.SelectCard(Nothing, nextMove, bh.declarer, GameStatus, cardsPanel(nextMove),
bh.trumpCard, Nothing, Me, bh.leadSuit)

is called. `ACP`

is a New `AutoCardPlay`

object.

With `nextMove`

, we control whose turn it is to play a card.

In `Sub`

`SelectCard`

, we make a difference between the first card of a trick and the other cards of a trick.

For the first card of a trick, the methods `SelectBestFirstCard`

and `WenzBestFirstCard`

are relevant.

For the other cards of a trick, the method `SelectBestReturnCard`

is normally used.

All of these methods may call other Functions or Subs like:

`OptimizeSelection`

`PlayTogether_WenzUsage`

`ContainsHandCardsStandardTrumps`

`GetLowOfHandCards`

`GetBestOfHandCards`

Most used method is `cardLessThan`

which is very important for comparing values of cards.

The original version is taken from [1]. I extended it because of the special value of „Overs“ and „Unders“ in the Schafkopf game.

At the end of the `SelectCard`

method, we use the following code:

If CurrentCard IsNot Nothing Then
CardsPanel.Children.Remove(CurrentCard)
MyForm.AutoPlaceCardOnTable(CurrentCard, PlayerID)
End If

to remove the `CurrentCard`

from the players `CardsPanel`

and call the `AutoPlaceCardOnTable`

method again to paste the `CurrentCard`

to the `CenterPanel`

and go on with **Auto Play**.

`TrickContent`

is another important class which we need for using `cardLessThan`

or other features.

Public Class TrickContent
Public Property IdLeadSuit As Integer
Public Property Card1 As String
Public Property Card2 As String
Public Property Card3 As String
Public Property Card4 As String
Public Property CurrentTrickWinner As Integer
Public Property PossibleWinnerPlayerID As Integer
Public Property PossibleWinnerCardString As String
Public Property CountCardsInTrick As Integer
Public Property GetSumOfCardValuesInTrick As Integer
Public Property PlayerIdCard1 As Integer
Public Property PlayerIdCard2 As Integer
Public Property PlayerIdCard3 As Integer
Public Property PlayerIdCard4 As Integer
Public Property PrevCard1 As String
Public Property PrevCard2 As String
Public Property PrevCard3 As String
Public Property PrevCard4 As String
End Class

#### Auto Play Feature

At the end of:

Public Sub AutoPlaceCardOnTable
. . .
. . .
Dim cardsPanel As Object = {Panel0, Panel1, Panel2, Panel3}
For i = 0 To 3
If GameStatus.ToString = "SpielAus" Then Exit Sub
If nextMove = 2 Then
If nextMove = 2 Then Exit Sub
Else
If nextMove = i Then ACP.SelectCard(Nothing, nextMove, bh.declarer,
GameStatus, cardsPanel(nextMove), _
bh.trumpCard, Nothing, Me, bh.leadSuit)
If nextMove = i Then If i > 0 _
Then GameStatus = GameState.AnotherCardInTrick
End If
Next
End Sub

We take a break `If nextMove = 2`

(this means Human Player needs to place a card) or run `ACP.SelectCard`

again if `nextMove`

`<> 2`

.

We **stop** the game If `GameStatus.ToString`

= "`SpielAus`

".

#### Implementing Schafkopf Rules

After some time, my coding resulted in many, many loops when checking a players cards and endless "rules" which are done with "`If`

, `Then`

, `ElseIf`

..." statements. But it seems to work very well now.

The main problem is how to find possible issues within those code parts.

The **new Version 2.6 or higher** reaches an improved playing level, like medium playing level.

Private Function SelectBestFirstCard(ByVal CardsPanel As Object, PlayerID As Integer,
DeclarerID As Integer, GameStatus As Object, sHandCards As Object, _
TrumpCardID As Integer,
CorrectCards As Object, MyForm As MainWindow, LeadSuitID As Integer) As PlayingCard
Dim MyBridge As New Bridge
Dim CurrentCard As PlayingCard
Dim bTeamDeclarer As Boolean
Dim bTeamOpponent As Boolean
If MyForm.GameOver = True Then Exit Function
If GameStatus.ToString = "SpielAus" Then MyForm.GameOver = True
If GameStatus.ToString = "SpielAus" Then Exit Function
If PlayerID <> DeclarerID And PlayerID <> MyForm.iCoSpieler Then
bTeamOpponent = True
If PlayerID = DeclarerID Or PlayerID = MyForm.iCoSpieler Then
bTeamDeclarer = True
With CardsPanel.Children
If .Count > 0 AndAlso bTeamDeclarer = True Then
For n = 0 To .Count - 1
If .Item(n).CardType = TrumpCardID Then
If sHandCards.ToString.Contains("A") = True AndAlso
DeclarerID = PlayerID Then
If MyForm.iTricks = 5 Or MyForm.iTricks = 6 Or
MyForm.iTricks = 7 Then
If SearchInCardsPanel(11, CardsPanel).CardType <>
TrumpCardID Then
CurrentCard = SearchInCardsPanel(11, CardsPanel)
End If
End If
Else
Dim s As String = .Item(n).CardShortName
If s.Contains(GetBestOfHandCards_
(CardsPanel, PlayerID, DeclarerID,
GameStatus, sHandCards, TrumpCardID, "RufAs", MyForm,
LeadSuitID)) Then
CurrentCard = CardsPanel.Children.Item(n)
End If
End If
End If
Next
End If
If .Count > 0 AndAlso bTeamDeclarer = True Then
For n = 0 To .Count - 1
If .Item(n).CardType <> TrumpCardID Then
Dim sO As String
If TrumpCardID = 4 Then sO = "X"
If TrumpCardID <> 4 Then sO = "O"
If .Item(n).CardShortName.Contains(sO) Or
.Item(n).CardShortName.Contains("U") Then
CurrentCard = .Item(n)
LeadSuitID = TrumpCardID
MyBridge.leadSuit = TrumpCardID
End If
End If
Next
End If
If bTeamOpponent = True Then
If .Count > 0 Then
For n = 0 To .Count - 1
If .Item(n).CardType = LeadSuitID Then
Dim sO As String
If TrumpCardID = 4 Then sO = "X"
If TrumpCardID <> 4 Then sO = "O"
If .Item(n).CardShortName.Contains(sO) = False AndAlso
.Item(n).CardShortName.Contains("U") = False Then
CurrentCard = .Item(n)
End If
End If
Next
End If
If .Count > 0 AndAlso MyForm.RufAs.IsAlreadyPlayed = False AndAlso
MyForm.iCoSpieler > -1 Then
For n = 0 To .Count - 1
If .Item(n).CardType <> TrumpCardID AndAlso
.Item(n).CardType = MyForm.RufAs.CardType Then
Dim sO As String
If TrumpCardID = 4 Then sO = "X"
If TrumpCardID <> 4 Then sO = "O"
If .Item(n).CardShortName.Contains(sO) = False AndAlso
.Item(n).CardShortName.Contains("U") = False Then
CurrentCard = .Item(n)
MyForm.RufAs.IsAlreadyPlayed = True
End If
End If
Next
End If
End If
If .Count > 0 AndAlso CurrentCard Is Nothing Then
For n = 0 To .Count - 1
CurrentCard = .Item(n)
Next
End If
End With
Return CurrentCard
End Function

#### About Version 2.6 or higher

This version includes all improvements from v1.5 to 2.3

And it includes a converted version of the project to **C#** what caused some trouble but finally it seems to work now. For unknown reasons, the C# 2.0 version had a worse playing level than the VB.NET one.

With version 2.6 or higher, both - VB.NET and C# - projects are at a comparable level.

## Conclusion

This is only a demo – it is not production ready.

But I think it will allow you to play `Schafkopf`

with / against your computer and have a lot of fun.

#### Final Note

I am very interested in feedback of any kind - problems, suggestions and other.

## Credits / Reference

## History

- 19
^{th }July, 2022 - VB and C# Version 2.7 include bug fixes and improved Team Playing. - 11
^{th }July, 2022 - replaced dead link, VB and C# Version 2.6 with an improved playing level - 7
^{th }July, 2022 - VB and C# Version 2.5 with an improved playing level - 1
^{st }July, 2022 - VB and C# Version 2.3 come along with some improvements - 25
^{th} June, 2022 - VB and C# Version 2.2 come along with some improvements - 21
^{st} June, 2022 - C# Version 2.1 with an improved playing level - 19
^{th} June, 2022 - Version 2.0 reaches almost medium playing level. **NEW: C# Version** of this project. - 15
^{th} June, 2022 - Version 1.8 reaches an improved playing level, almost like medium playing level and fixes some bugs - 12
^{th} June, 2022 - Version 1.7 reaches an improved playing level, almost like medium playing level and includes some bug fixes as well - 10
^{th} June, 2022 - Version 1.6 improves Auto Playing Level and includes some bug fixes as well - 7
^{th} June, 2022 - Version 1.5 allows an improved Auto Playing Level and includes some bug fixes as well - 4
^{th} June, 2022 - Initial submission