Blackjack
blackjack.vxml
xml version="1.0" encoding="UTF-8"
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml">
<meta name="description" content="BlackJack"/>
<meta name="author" content="OptimSys, s.r.o., Czech Republic (http://www.optimsys.cz)"/>
<meta name="copyright" content="free for any purpose"/>
<var name="cards"/>
<var name="currCard" expr="0"/>
<var name="userCards"/>
<var name="compCards"/>
<script> <![CDATA[
function shuffle() {
for (var i = 0; i < 52; i++) {
cards[i] = i;
}
for (var i = 0; i < 51; i++) {
var j = Math.floor(Math.random()*(52-i))+i;
var k = cards[i];
cards[i] = cards[j];
cards[j] = k;
}
}
function cardDescription (cardNum) {
var suit = Math.floor (cardNum / 13);
var rank = cardNum % 13;
var cardDesc;
switch (rank) {
case 0: cardDesc = "2 of "; break;
case 1: cardDesc = "3 of "; break;
case 2: cardDesc = "4 of "; break;
case 3: cardDesc = "5 of "; break;
case 4: cardDesc = "6 of "; break;
case 5: cardDesc = "7 of "; break;
case 6: cardDesc = "8 of "; break;
case 7: cardDesc = "9 of "; break;
case 8: cardDesc = "10 of "; break;
case 9: cardDesc = "jack of "; break;
case 10: cardDesc = "queen of "; break;
case 11: cardDesc = "king of "; break;
case 12: cardDesc = "ace of "; break;
}
switch (suit) {
case 0: cardDesc += "clubs"; break;
case 1: cardDesc += "hearts"; break;
case 2: cardDesc += "diamonds"; break;
case 3: cardDesc += "spades"; break;
}
return cardDesc;
}
function newCardForUser() {
userCards[userCards.length] = cards[currCard];
currCard++;
}
function lastUserCardDesc() {
return cardDescription(userCards[userCards.length-1]);
}
function newCardForComp() {
compCards[compCards.length] = cards[currCard];
currCard++;
}
function lastCompCardDesc() {
return cardDescription(compCards[compCards.length-1]);
}
function valOfCard (cardNum) {
var rank = cardNum % 13;
switch (rank) {
case 9: return 10;
case 10: return 10;
case 11: return 10;
case 12: return 11;
default: return rank+2;
}
}
function valOfCards (c) {
var val = 0;
var i;
var aceNum = 0;
for (var i = 0; i < c.length; i++) {
var v = valOfCard(c[i]);
if (v == 11) aceNum++;
val += v;
}
while (val > 21 && aceNum > 0) {
val -= 10; // ace can be counted as 1 instead of 11 if needed
aceNum--;
}
return val;
}
function softHand (c) { // are all aces counted as 11?
var val = 0;
var i;
var aceNum = 0;
for (var i = 0; i < c.length; i++) {
var v = valOfCard(c[i]);
if (v == 11) aceNum++;
val += v;
}
while (val > 21 && aceNum > 0) {
val -= 10; // ace can be counted as 1 instead of 11 if needed
aceNum--;
}
return aceNum > 0;
}
function valOfUserCards() {
return valOfCards (userCards);
}
function valOfCompCards() {
return valOfCards (compCards);
}
function shouldCompTakeCard() { // strategy of the computer
if (softHand (compCards)) return true;
var val = valOfCompCards();
if (val <= 11) return true;
if (Math.random() < 0.25) return true; // risk
if (Math.random() < 1/(val-11)) return true;
return false;
}
]]> </script>
<form id="start">
<block>
<prompt>Welcome to blackjack</prompt>
<script>
cards = new Array(52);
</script>
<goto next="#new_game"/>
</block>
</form>
<form id="new_game">
<field name="yesno">
<noinput> Hey, don't sleep and say something! </noinput>
<nomatch> I didn't understand you. </nomatch>
<prompt>Do you want to play a new game?</prompt>
<grammar src="yesno.grxml"/>
<filled>
<if cond="yesno == 'yes'">
<goto next="#start_game"/>
<else/>
<goto next="#end"/>
</if>
</filled>
</field>
</form>
<form id="start_game">
<block>
<prompt>
I am shuffeling the cards. We start with two cards for each.
</prompt>
<script>
userCards = new Array;
compCards = new Array;
shuffle();
newCardForUser();
newCardForUser();
newCardForComp();
newCardForComp();
</script>
<prompt>
You got <value expr="cardDescription(userCards[0])"/>
and <value expr="cardDescription(userCards[1])"/>.
</prompt>
<goto next="#game_eval"/>
</block>
</form>
<form id="game_eval">
<block>
<var name="userVal" expr="valOfUserCards()"/>
<var name="compVal" expr="valOfCompCards()"/>
<prompt>Value of your cards is <value expr="userVal"/></prompt>
<if cond="userVal > 21">
<prompt>You lost the game.</prompt>
<goto next="#new_game"/>
</if>
<if cond="userVal == 21 || compVal > 21">
<prompt>Value of my cards is <value expr="compVal"/></prompt>
<prompt>You won the game!</prompt>
<goto next="#new_game"/>
</if>
<if cond="compVal == 21">
<prompt>Value of my cards is <value expr="compVal"/></prompt>
<prompt>You lost the game.</prompt>
<goto next="#new_game"/>
</if>
<goto next="#decision"/>
</block>
</form>
<form id="decision">
<field name="userDecision">
<noinput> Hey, don't sleep and say something! </noinput>
<nomatch> I didn't understand you. </nomatch>
<prompt>Do you want one more card?</prompt>
<grammar src="yesno.grxml"/>
<grammar src="nextcard.grxml"/>
<filled>
<if cond="userDecision == 'yes'">
<script>newCardForUser();</script>
<if cond="valOfUserCards() >= 21">
<prompt>
You got <value expr="lastUserCardDesc()"/>
</prompt>
<goto next="#game_eval"/>
</if>
</if>
<var name="compDecision" expr="shouldCompTakeCard()"/>
<if cond="compDecision == true">
<script>newCardForComp();</script>
</if>
<if cond="userDecision == 'yes' && compDecision == true">
<prompt>
I am giving you <value expr="lastUserCardDesc()"/> and I also take
a card.
</prompt>
<elseif cond="userDecision == 'yes' && compDecision == false"/>
<prompt>
I am giving you <value expr="lastUserCardDesc()"/>. I will take
no card.
</prompt>
<elseif cond="userDecision == 'no' && compDecision == true"/>
<prompt>OK, you don't want a card, but I will take one.</prompt>
<else/>
<prompt>I also don't want more cards. The game is finished.</prompt>
<goto next="#game_finished"/>
</if>
<goto next="#game_eval"/>
</filled>
</field>
</form>
<form id="game_finished">
<block>
<var name="userVal" expr="valOfUserCards()"/>
<var name="compVal" expr="valOfCompCards()"/>
<prompt>Value of your cards is <value expr="userVal"/></prompt>
<prompt>Value of my cards is <value expr="compVal"/></prompt>
<if cond="userVal >= compVal">
<prompt>You won the game!</prompt>
<else/>
<prompt>You lost the game.</prompt>
</if>
<goto next="#new_game"/>
</block>
</form>
<form id="end">
<block>
I hope you enjoyed the game. Goodbye.
</block>
</form>
</vxml>
nextcard.grxml
xml version="1.0" encoding="UTF-8"
<grammar root="main" version="1.0" xmllang="en" tag-format="semantics/1.0-literals">
<meta name="description" content="grammar for accepting/refusing another card"/>
<meta name="author" content="OptimSys, s.r.o., Czech Republic (http://www.optimsys.cz)"/>
<meta name="copyright" content="free for any purpose"/>
<rule id="main" scope="public">
<item repeat="0-1"> please </item>
<one-of>
<item><ruleref uri="#yes"/><tag>yes</tag></item>
<item><ruleref uri="#no"/><tag>no</tag></item>
</one-of>
<item repeat="0-1"> please </item>
</rule>
<rule id="yes">
<one-of>
<item>hit</item>
<item>
<item repeat="0-1">
<one-of>
<item>I want</item>
<item>give me</item>
</one-of>
</item>
<item repeat="0-1"> one </item>
more
<item repeat="0-1">
<one-of>
<item> card </item>
<item> cards </item>
</one-of>
</item>
</item>
</one-of>
</rule>
<rule id="no">
<one-of>
<item>stand</item>
<item>
<item repeat="0-1">
I
<one-of>
<item> want to </item>
<item> will </item>
</one-of>
</item>
stay
</item>
<item>
<item repeat="0-1">
I
<one-of>
<item> don't </item>
<item> do not </item>
</one-of>
</item>
want
<item repeat="0-1"> more </item>
<item repeat="0-1"> cards </item>
</item>
<item>
<item repeat="0-1"> no more </item>
cards
</item>
<item>
<item repeat="0-1"> I have </item>
enough
</item>
</one-of>
</rule>
</grammar>
yesno.grxml
xml version="1.0" encoding="UTF-8"
<grammar root="main" version="1.0" xmllang="en" tag-format="semantics/1.0-literals">
<meta name="description" content="yes/no grammar"/>
<meta name="author" content="OptimSys, s.r.o., Czech Republic (http://www.optimsys.cz)"/>
<meta name="copyright" content="free for any purpose"/>
<rule id="main" scope="public">
<one-of>
<item><ruleref uri="#yes"/><tag>yes</tag></item>
<item><ruleref uri="#no"/><tag>no</tag></item>
</one-of>
</rule>
<rule id="yes">
<one-of>
<item>yes</item>
<item>yeah</item>
<item>yep</item>
<item>sure</item>
</one-of>
</rule>
<rule id="no">
<one-of>
<item>no</item>
<item>not</item>
<item>nope</item>
</one-of>
</rule>
</grammar>