Home -> Support -> VoiceXML Examples

Iterated Prisoner's Dilemma

config.vxml
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml">

<meta name="description" content="Configuration of the Iterated Prisoner's Dilemma"/>
<meta name="author" content="Laboratory of Speech and Dialogue, Faculty of
  Informatics, Masaryk University Brno, Czech Republic"/>
<meta name="copyright" content="free for any purpose"/>

<!--
  The Prisoner's Dilemma is an important problem of the theory of cooperation.
  It is based on the following scenario: Two accomplices in a crime are caught
  and placed in separate cells so that they cannot communicate. A public
  attorney tries to induce each one to turn evidence against the other
  (i.e., to "defect"). Refusing to turn evidence against the other is to
  "cooperate".

  If both cooperate they will be both jailed for one year.
  If both defect they will be both jailed for three years.
  If one cooperates and one defects then that one who cooperates will be jailed
    for six years and that one who defects will be freed.

  The Iterated Prisoner's Dilemma is a game in which the Prisoner's Dilemma is
  repeated with the same players several times and both players know the
  outcomes of previous iterations. The task is to find the optimal strategy
  for the Iterated Prisoner's Dilemma.

  In order to make the problem even more interesting, 'noise' has been added
  to the game - each computer's decision is inverted with certain probability.

  Various parameters of the game and the strategy itself can be changed below.

  This VoiceXML version of the problem has been presented at the 5th Summer
  School of the European Masters in Language and Speech program in Bonn,
  July 12-16, 2004 (http://www.ikp.uni-bonn.de/emls/index.html).
-->

<!-- number of game iterations -->
<var name="iterCount" expr="15"/>

<!-- probability of 'noise', i.e. probability of inverting
     computer's answer -->
<var name="noiseProb" expr="0.1"/>

<!-- if both cooperate, price for both -->
<var name="price2Coop" expr="1"/>

<!-- if neither cooperates, price for both -->
<var name="price2NotCoop" expr="3"/>

<!-- if one cooperates, price for that one who cooperates -->
<var name="price1Coop" expr="6"/>

<!-- if one cooperates, price for that one who does not cooperate -->
<var name="price1NotCoop" expr="0"/>

<!-- array containing user's answers for all iterations -->
<var name="userAnswers" expr="new Array()"/>

<!-- array containing computers's answers for all iterations -->
<var name="compAnswers" expr="new Array()"/>

<!-- experiment with the strategy -->
<script> <![CDATA[
  function computerStrategy() {
    // based on the history stored in the userAnswers and compAnswers
    // arrays return true if you want to cooperate and false if you
    // don't want to cooperate.

    // couple of hints:
    // 1. arrays userAnswers and compAnswers are accessible in this
    //    script
    // 2. any other variables you want to use must be declared
    //    first by 'var <variableName>;' statement (see e.g. the
    //    'i' variable in the 'for' cycle below)
    // 3. the length of an array 'A' can be obtained as 'A.length'


    // Tit For Tat strategy: cooperate at first and then repeat the other's
    // move.
    if (userAnswers.length == 0) return true;
    else return userAnswers[userAnswers.length-1];
  }
]]> </script>

</vxml>
prisoner_version1.vxml
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml" application="config.vxml">

<meta name="description" content="Iterated Prisoner's Dilemma"/>
<meta name="author" content="OptimSys, s.r.o., Czech Republic (http://www.optimsys.cz)"/>
<meta name="copyright" content="free for any purpose"/>

<!-- see config.vxml for instuctions -->

<!-- links -->
<link event="help">
  <grammar src="help.grxml"/>
</link>

<!-- global reactions on some common situations -->
<help> Sorry, no help available </help>
<noinput> Hey, don't sleep and say something! </noinput>
<nomatch> I didn't understand you. </nomatch>
<nomatch count="4">
  Sorry, I don't understand again. I am giving up. Good Bye.
  <log>***DO NOT UNDERSTAND USER, THE GAME IS INCOMPLETE***</log>
  <exit/>
</nomatch>
<catch event="connection.disconnect.hangup">
  <log>***USER HUNG UP, THE GAME IS INCOMPLETE***</log>
</catch>

<!-- some global variables -->
<var name="iterNo" expr="0"/>
  <!-- iteration number -->
<var name="totalPriceUser" expr="0"/>
  <!-- total price achieved by the user -->
<var name="totalPriceComp" expr="0"/>
  <!-- total price achieved by the computer -->

<!-- the interpretation starts with this form -->
<form id="start">
  <block>
    <prompt>Welcome to the iterative prisoner's dilema game.</prompt>
    <prompt>We will play <value expr="iterCount"/> iterations.</prompt>
    <prompt>Probability of noise is <value expr="noiseProb"/>.</prompt>
    <prompt>If you need help, say help at any time.</prompt>
    <goto next="#new_game"/>
  </block>
</form>

<form id="new_game">
  <field name="yesno">
    <prompt>Do you want to start the game?</prompt>
    <grammar src="yesno.grxml"/>

    <filled>
      <if cond="yesno == true">
        <!-- user wants to start the game -->

        <log>============</log>
        <log>Game started</log>
        <log>============</log>

        Let's start!
        <goto next="#game_move"/>
      <else/>
        <!-- user does not want to start the game -->
        OK, you can play the game later. Bye.
        <exit/>
      </if>
    </filled>

    <help>Say 'yes' or 'no'.</help>
    <nomatch>
      I didn't understand you. Expected answers are 'yes' or 'no'
    </nomatch>
  </field>
</form>

<form id="game_move">
  <block>
    <!-- increase the iteration number and report it to the user -->
    <assign name="iterNo" expr="iterNo+1"/>
    <prompt>
      Iteration <value expr="iterNo"/>.
    </prompt>

    <!-- play for computer -->
    <script> <![CDATA[
      if (Math.random() < noiseProb) {
        // incorporate the noise
        compAnswers.push (!computerStrategy());
      }
      else {
        compAnswers.push (computerStrategy());
      }
    ]]> </script>
  </block>

  <field name="cooperation">
    <prompt>Do you want to cooperate?</prompt>
    <grammar src="yesno.grxml"/>

    <filled>
      <!-- user specified his/her 'move' -->

      <!-- store the user's move -->
      <script>
        userAnswers.push (cooperation);
      </script>
    </filled>

    <help>Say 'yes' if you want to cooperate, say 'no' otherwise.</help>
    <noinput>Hey, don't sleep! Say 'yes' or 'no'.</noinput>
    <nomatch>
      I didn't understand you. Expected answers are 'yes' or 'no'.
    </nomatch>
  </field>

  <block>
    <!-- calculate and report the results of this iteration to the user -->
    <if cond="userAnswers[userAnswers.length-1] == true &amp;&amp;
              compAnswers[compAnswers.length-1] == true">
      <assign name="totalPriceUser" expr="totalPriceUser + price2Coop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price2Coop"/>
      <prompt>Computer cooperates as well.</prompt>
      <prompt>You both got <value expr="price2Coop"/> years.</prompt>

    <elseif cond="userAnswers[userAnswers.length-1] == false &amp;&amp;
              compAnswers[compAnswers.length-1] == true"/>
      <assign name="totalPriceUser" expr="totalPriceUser + price1NotCoop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price1Coop"/>
      <prompt>Computer cooperates.</prompt>
      <prompt><value expr="price1NotCoop"/> years for you,
              <value expr="price1Coop"/> years for computer.</prompt>

    <elseif cond="userAnswers[userAnswers.length-1] == true &amp;&amp;
              compAnswers[compAnswers.length-1] == false"/>
      <assign name="totalPriceUser" expr="totalPriceUser + price1Coop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price1NotCoop"/>
      <prompt>Computer decided to defect.</prompt>
      <prompt><value expr="price1Coop"/> years for you,
              <value expr="price1NotCoop"/> years for computer.</prompt>

    <else/>
      <!-- userAnswers[userAnswers.length-1] == false &amp;&amp;
           compAnswers[compAnswers.length-1] == false"> -->
      <assign name="totalPriceUser" expr="totalPriceUser + price2NotCoop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price2NotCoop"/>
      <prompt>Computer defects as well.</prompt>
      <prompt>You both got <value expr="price2NotCoop"/> years.</prompt>
    </if>

    <!-- log the answer -->
    <log>
      Iteration <value expr="iterNo"/>,
      U: <value expr="userAnswers[userAnswers.length-1]"/>
      C: <value expr="compAnswers[compAnswers.length-1]"/>
    </log>

    <if cond="iterNo == iterCount">
      <goto next="#game_eval"/>
    <else/>
      <goto next="#game_move"/>
    </if>
  </block>

</form>

<form id="game_eval">
  <block>
    <!-- report final results -->
    <prompt>The game is finished.</prompt>
    <prompt>You got <value expr="totalPriceUser"/> years.</prompt>
    <prompt>Computer got <value expr="totalPriceComp"/> years.</prompt>
    <prompt>I hope you enjoyed the game. Goodbye.</prompt>
    <log>
      U total: <value expr="totalPriceUser"/>
      C total: <value expr="totalPriceComp"/>
    </log>
  </block>
</form>

</vxml>
prisoner_version2.vxml
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml" application="config.vxml">

<meta name="description" content="Iterated Prisoner's Dilemma"/>
<meta name="author" content="OptimSys, s.r.o., Czech Republic (http://www.optimsys.cz)"/>
<meta name="copyright" content="free for any purpose"/>

<!-- see config.vxml for instuctions -->

<!-- links -->
<link event="help">
  <grammar src="help.grxml"/>
</link>

<!-- global reactions on some common situations -->
<help> Sorry, no help available </help>
<noinput> Hey, don't sleep and say something! </noinput>
<nomatch> I didn't understand you. </nomatch>
<nomatch count="4">
  Sorry, I don't understand again. I am giving up. Good Bye.
  <log>***DO NOT UNDERSTAND USER, THE GAME IS INCOMPLETE***</log>
  <exit/>
</nomatch>
<catch event="connection.disconnect.hangup">
  <log>***USER HUNG UP, THE GAME IS INCOMPLETE***</log>
</catch>

<!-- some global variables -->
<var name="iterNo" expr="0"/>
  <!-- iteration number -->
<var name="totalPriceUser" expr="0"/>
  <!-- total price achieved by the user -->
<var name="totalPriceComp" expr="0"/>
  <!-- total price achieved by the computer -->

<!-- the interpretation starts with this form -->
<form id="start">
  <block>
    <prompt>Welcome to the iterative prisoner's dilema game.</prompt>
    <prompt>We will play <value expr="iterCount"/> iterations.</prompt>
    <prompt>Probability of noise is <value expr="noiseProb"/>.</prompt>
    <prompt>If you need help, say help at any time.</prompt>
    <goto next="#new_game"/>
  </block>
</form>

<form id="new_game">
  <field name="yesno">
    <prompt>Do you want to start the game?</prompt>
    <grammar src="yesno.grxml"/>

    <filled>
      <if cond="yesno == true">
        <!-- user wants to start the game -->

        <log>============</log>
        <log>Game started</log>
        <log>============</log>

        Let's start!
        <goto next="#game_move"/>
      <else/>
        <!-- user does not want to start the game -->
        OK, you can play the game later. Bye.
        <exit/>
      </if>
    </filled>

    <help>Do you want to start the game?. Say 'yes' or 'no'.</help>
    <nomatch>
      I didn't understand you. Expected answers are 'yes' or 'no'
    </nomatch>
  </field>
</form>

<form id="game_move">
  <block>
    <!-- increase the iteration number and report it to the user -->
    <assign name="iterNo" expr="iterNo+1"/>
    <prompt>
      Iteration <value expr="iterNo"/>.
    </prompt>

    <!-- play for computer -->
    <script> <![CDATA[
      if (Math.random() < noiseProb) {
        // incorporate the noise
        compAnswers.push (!computerStrategy());
      }
      else {
        compAnswers.push (computerStrategy());
      }
    ]]> </script>
  </block>

  <grammar src="cooperation.grxml"/>
  <initial name="skip_mixed">
    So, what is your decision.
    <nomatch>
      I didn't understand you. Do you want to cooperate or defect?
    </nomatch>
    <nomatch count="2">
      I didn't understand you again. I will ask you in another way.
      <assign name="skip_mixed" expr="true"/>
      <reprompt/>
    </nomatch>
    <help>You have to say whether you want to cooperate or defect.</help>
  </initial>

  <field name="cooperation">
    <prompt>Do you want to cooperate? Say 'yes' or 'no'.</prompt>
    <grammar src="yesno.grxml"/>

    <filled>
      <!-- user specified his/her 'move' -->

      <!-- store the user's move -->
      <script>
        userAnswers.push (cooperation);
      </script>
    </filled>

    <help>Say 'yes' if you want to cooperate, say 'no' otherwise.</help>
    <noinput>Hey, don't sleep! Say 'yes' or 'no'.</noinput>
    <nomatch>
      I didn't understand you. Expected answers are 'yes' or 'no'.
    </nomatch>
  </field>

  <block>
    <!-- calculate and report the results of this iteration to the user -->
    <if cond="userAnswers[userAnswers.length-1] == true &amp;&amp;
              compAnswers[compAnswers.length-1] == true">
      <assign name="totalPriceUser" expr="totalPriceUser + price2Coop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price2Coop"/>
      <prompt>Computer cooperates as well.</prompt>
      <prompt>You both got <value expr="price2Coop"/> years.</prompt>

    <elseif cond="userAnswers[userAnswers.length-1] == false &amp;&amp;
              compAnswers[compAnswers.length-1] == true"/>
      <assign name="totalPriceUser" expr="totalPriceUser + price1NotCoop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price1Coop"/>
      <prompt>Computer cooperates.</prompt>
      <prompt><value expr="price1NotCoop"/> years for you,
              <value expr="price1Coop"/> years for computer.</prompt>

    <elseif cond="userAnswers[userAnswers.length-1] == true &amp;&amp;
              compAnswers[compAnswers.length-1] == false"/>
      <assign name="totalPriceUser" expr="totalPriceUser + price1Coop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price1NotCoop"/>
      <prompt>Computer decided to defect.</prompt>
      <prompt><value expr="price1Coop"/> years for you,
              <value expr="price1NotCoop"/> years for computer.</prompt>

    <else/>
      <!-- userAnswers[userAnswers.length-1] == false &amp;&amp;
           compAnswers[compAnswers.length-1] == false"> -->
      <assign name="totalPriceUser" expr="totalPriceUser + price2NotCoop"/>
      <assign name="totalPriceComp" expr="totalPriceComp + price2NotCoop"/>
      <prompt>Computer defects as well.</prompt>
      <prompt>You both got <value expr="price2NotCoop"/> years.</prompt>
    </if>

    <!-- log the answer -->
    <log>
      Iteration <value expr="iterNo"/>,
      U: <value expr="userAnswers[userAnswers.length-1]"/>
      C: <value expr="compAnswers[compAnswers.length-1]"/>
    </log>

    <if cond="iterNo == iterCount">
      <goto next="#game_eval"/>
    <else/>
      <goto next="#game_move"/>
    </if>
  </block>

</form>

<form id="game_eval">
  <block>
    <!-- report final results -->
    <prompt>The game is finished.</prompt>
    <prompt>You got <value expr="totalPriceUser"/> years.</prompt>
    <prompt>Computer got <value expr="totalPriceComp"/> years.</prompt>
    <prompt>I hope you enjoyed the game. Goodbye.</prompt>
    <log>
      U total: <value expr="totalPriceUser"/>
      C total: <value expr="totalPriceComp"/>
    </log>
  </block>
</form>

</vxml>
cooperation.grxml
<?xml version="1.0" encoding="UTF-8"?>
<grammar root="main" version="1.0" xml:lang="en">

  <meta name="description" content="grammar for expressing decision about the next move"/>
  <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="#cooperate"/><tag>out.cooperation = true;</tag></item>
      <item><ruleref uri="#defect"/><tag>out.cooperation = false;</tag></item>
    </one-of>
  </rule>

  <rule id="cooperate">
    <item repeat="0-1">I</item>
    <item repeat="0-1">want</item>
    <item repeat="0-1">will</item>
    <item repeat="0-1">to</item>
    <item repeat="0-1">be</item>
    <one-of>
      <item>cooperate</item>
      <item>cooperative</item>
    </one-of>
  </rule>

  <rule id="defect">
    <item repeat="0-1">I</item>
    <item repeat="0-1">want</item>
    <item repeat="0-1">will</item>
    <item repeat="0-1">to</item>
    <one-of>
      <item>defect</item>
      <item>betray</item>
    </one-of>
  </rule>

</grammar>
help.grxml
<?xml version="1.0" encoding="UTF-8"?>
<grammar root="main" version="1.0" xml:lang="en">

  <meta name="description" content="help 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">
    <item repeat="0-1"> please </item>
    <item repeat="0-1"> I need </item>
    help
    <item repeat="0-1"> me </item>
    <item repeat="0-1"> please </item>
  </rule>
</grammar>
yesno.grxml
<?xml version="1.0" encoding="UTF-8"?>
<grammar root="main" version="1.0" xml:lang="en">

  <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>out=true</tag></item>
      <item><ruleref uri="#no"/><tag>out=false</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>