Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Tuesday, 2 May 2017

Pokemon TCG: Greedy Dice

Pokemon have been quite a thing in the Sniff household for the last year or two (before "Go" and Sun and Moon made them trendy again), but a recent expansion has been into the Trading Card Game. For those who haven't played, its a card game played with Pokemon cards. However while the basic game is reasonably fun, what makes it interesting is that you can choose what cards make up a your deck. When you get ripped off at Asda's for a "booster pack" it provides 10 new cards, which you can use to replace  cards previously in your deck. Generally you can think of it as a giant game of rock paper scissors, where some cards are better than others, but even some of the weaker ones can come into their own under the right circumstances, so picking the right cards to use is critical.

One card such card is called "Greedy Dice". Within the game there is a pile of 6 "prize" cards, dealt randomly from your deck at the start of the game. Each time you knock out an opponent you get a prize card from your own pile, and if you get all 6 you win! The rule for greedy dice is, if its drawn from the prize pile, you toss a coin and if its heads you get to take another prize card! Two for the price of one!

However once you actually think about it, is it really such a great card to have in your deck? You're limited to 60 cards, so if you put a GD card in, you need to take something out, so you need to be pretty sure its worth it.

So lets do the maths... from 60 cards you have a 1 in 10 chance that one of the 6 prize cards is the GD card. So you'll get something good 1 game in 10? Well not so fast... there are six prize cards, but GD is only useful if one of the first 5. Getting to take an extra prize card does'nt' really help if you've already won. Worst, we forgot about the coin toss, so we get a benefit less than 1 game in 20.

OK that's a bit pointless, but what if we go for it! You're allowed to have up to 4 of each card in your deck, so what happens if we put 4 of them in. That's a big chunk of deck space, but hopefully we'll start to get something out of it...

Now the maths gets a bit more complex, so lets write a program:

make cardsInDeck number 60
make cardsInPrizes number 6
make greedy number 4

make cards list of boolean
make prizes list of boolean

So here we've got 60 cards in a deck, 6 of them are placed as prizes, and of the whole deck 4 of them are greedy dice. To represent the deck and the prizes I've made two lists of booleans - we don't actually care what the cards are, so I'm simply going to store yes or no to record if its a GD.

when game
.delete all of cards
.delete all of prizes
.repeat cardsInDeck
..add no to cards
.repeat greedy
..delete item 1 of cards
..add yes to cards

So here we go setting up a game. We clear out the cards, and the prizes, and then add 60 regular cards to the list. Then we replace 4 of those with greedy dice. Now we're ready to play!

The game starts when we deal our 6 prizes:

.repeat cardsInPrizes
..set deal to pick random 1 to length of cards
..add item deal of cards to prizes
..delete item deal of cards

Here we pick six random cards from the deck and place them in the prizes. Finally we just need to see you many of the first 5 prizes are GD:

.repeat cardsInPrizes-1
..if item 1 of prizes = yes
...if pick random 1 to 2 = 1
....change found by 1
..delete item 1 of prizes

We pick up the first prize card and if its a GD we toss a coin. If its heads then we've found (and successfully used) a Greedy Dice card. If its tails then we actually loose out in the game, as normally we'd get a useful card as a prize - GD is useless except to win a second prize. We keep track of the number of times we benefit.

make games number 1000000

when start
.set found to 0
.repeat games
..broadcast game and wait
.say join  "found "  join [found]  join " in "  join [games ] " games"
.say [found/games]

Now all we need to do is play a million games! A fraction of a second later, we discover we got an extra prize 167360 times in 1 million games. Thats 16.7% or about once every 6 games.
Of course I'm not the first person to figure this out:  Here some one comes up with the number: 15.83% That's a little but lower than our result, but you read closely you'll see that he's calculated the probability that you'll get one or more useful GD in any game, whereas we've counted the number of times GD's help - sometime more than one per game.

To make the two calculations match, we need to change our scoring:

.repeat cardsInPrizes-1
..if item 1 of prizes = yes
...if pick random 1 to 2 = 1
....change found by 1
....stop script
..delete item 1 of prizes

Now when we get a good GD card we call it a win for that match, and stop searching. Doing that we get an exact match up.

So not looking good, and about 1 game in 6 to see any benefit. However if you're new to TCG you might want to try the half deck variant - 30 cards and 3 prizes makes the games a little quicker, and its much easier to build a deck from the the cards you happen to have, rather than having to buy extras to make up a sensible 60. If we have 4 GD from 30 we're more likely to pick them for each prize slot (at the cost of taking up a greater proportion of deck space), which should help... except now we only draw 2 useful prize cards instead of 5, bringing the gain down to a useless 13%.

Either way you can probably do something more interesting with those 4 card slots than GD. Maybe in some future expansion they'll add a trainer card which lets you do something more useful with the GD card, but for now its just a dead card!