import gambit

g=gambit.Game.new_tree()

g.title="9x9"

"""
Explanation: <center><b>QRE analysis of a sender-receiver game</b></center>
<center>Valeria Burdea, December 2016</center>
This is a 2-player sequential game the structure of which is inspired by Glazer and Rubinstein (2004, 2006). In the first stage, the sender is dealt 2 cards - one card orange, one card blue. Each card can take a value between 1 and 9; each combination of values is equally likely. A hand is good if the sum of the two cards is at least 9; a hand is bad otherwise. Upon observing the two cards, the sender chooses one to reveal to the receiver. The receiver observes the revealed card and chooses an action between 'Accept' and 'Reject'. The incentives are such that the sender would always want the receiver to accept, while the receiver would only want to accept if the hand is good and reject otherwise.
This game is studied experimentally in a working paper, "Communication with partially verifiable information: An experiment" by Valeria Burdea, Maria Montero, and Martin Sefton.
End of explanation
"""


sender=g.players.add("Sender")
receiver=g.players.add("Receiver")

"""
Explanation: Adding the two players:
End of explanation
"""


move=g.root.append_move(g.players.chance, 81)

i=0
b=1
while i<81 and b<10:
    for o in range(1, 10):
        move.actions[i].label=str(b)+str(o)
        i=i+1
    b=b+1

"""
Explanation: Adding the chance moves. There are 81 such moves, as there are 81 (9x9) possible combinations of card values:
End of explanation
"""


for j in range(0,81):
    moves=g.root.children[j].append_move(sender,2)
    moves.label='s'+move.actions[j].label
    moves.actions[0].label=move.actions[j].label[0]
    moves.actions[1].label=move.actions[j].label[1]

"""
Explanation: For each of the 81 states, the sender has two actions: reveal the value on the orange card (action 0) or the value on the blue card (action 1). We add these actions at different information sets as the sender has perfect information about the state of the world:
End of explanation
"""


first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='1':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='1':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='1':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='1'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='1':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='2':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='2':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='2':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='2'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='2':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='3':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='3':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='3':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='3'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='3':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='4':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='4':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='4':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='4'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='4':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='5':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='5':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='5':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='5'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='5':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='6':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='6':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='6':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='6'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='6':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='7':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='7':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='7':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='7'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='7':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='8':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='8':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='8':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='8'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='8':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

first=0
for i in range(0,81):
    if first>0:
        if g.root.children[i].infoset.actions[0].label=='9':
            g.root.children[i].children[0].append_move(mover)
        if g.root.children[i].infoset.actions[1].label=='9':
            g.root.children[i].children[1].append_move(mover)
    t=0
    while first<1 and t<2:
        if g.root.children[i].infoset.actions[t].label=='9':
            mover=g.root.children[i].children[t].append_move(receiver,2)
            mover.label='9'
            mover.actions[0].label="Accept"
            mover.actions[1].label="Reject"
            if t==0 and g.root.children[i].infoset.actions[1].label=='9':
                g.root.children[i].children[1].append_move(mover)
            t=t+2
            first=1
        else:
            t=t+1

"""
Explanation: For each value revealed the receiver has two actions: 'Accept' and 'Reject'. We assume the receiver is colour blind, so she only has 9 information sets corresponding to the 9 possible values on either card. To do this iteratively, we define the move for the first time that card value is observed and then, every other time we append the same previously defined move. We repeat this process for each information set of the receiver..
End of explanation
"""


accept_good=g.outcomes.add("R accepts good hand")
accept_good[0]=1
accept_good[1]=1

reject_good=g.outcomes.add("R rejects good hand")
reject_good[0]=0
reject_good[1]=0

accept_bad=g.outcomes.add("R accepts bad hand")
accept_bad[0]=1
accept_bad[1]=0

reject_bad=g.outcomes.add("R rejects bad hand")
reject_bad[0]=0
reject_bad[1]=1

"""
Explanation: We now define the outcomes. There are 4 such possible outcomes depending on whether the receiver accepts or rejects and whether the state is good or bad.
End of explanation
"""


for i in range(0,81):
    hand=int(g.root.children[i].infoset.actions[0].label)+int(g.root.children[i].infoset.actions[1].label)
    if hand>8:
        g.root.children[i].children[0].children[0].outcome=accept_good
        g.root.children[i].children[0].children[1].outcome=reject_good
        g.root.children[i].children[1].children[0].outcome=accept_good
        g.root.children[i].children[1].children[1].outcome=reject_good
    else:
        g.root.children[i].children[0].children[0].outcome=accept_bad
        g.root.children[i].children[0].children[1].outcome=reject_bad
        g.root.children[i].children[1].children[0].outcome=accept_bad
        g.root.children[i].children[1].children[1].outcome=reject_bad

"""
Explanation: We proceed by appending the previously defined outcome pairs to the corresonding leafs.
End of explanation
"""


with file("extensive9x9.efg", "w") as f:
    f.write(g.write('efg'))

"""
Explanation: We write the game out to disk in order to be able to use the Gambit command-line tools to compute the principle branch of the QRE.
End of explanation
"""


!gambit-logit extensive9x9.efg

"""
Explanation: Computing the principal branch of the QRE:
End of explanation
"""


