Creating a variant of Binmore's two-population replicator dynamic model of the ultimatum game

Creating the game

A ultimatum game played with a 10-slice cake and acceptance thresholds has the following payoff matrix for ultimatum proposers:


Acceptance Threshold

0
1
2
3
4
5
6
7
8
9
10
Offer 0
10
0
0
0
0
0
0
0
0
0
0
Offer 1
9
9
0
0
0
0
0
0
0
0
0
Offer 2
8
8
8
0
0
0
0
0
0
0
0
Offer 3
7
7
7
7
0
0
0
0
0
0
0
Offer 4
6
6
6
6
6
0
0
0
0
0
0
Offer 5
5
5
5
5
5
5
0
0
0
0
0
Offer 6
4
4
4
4
4
4
4
0
0
0
0
Offer 7
3
3
3
3
3
3
3
3
0
0
0
Offer 8
2
2
2
2
2
2
2
2
2
0
0
Offer 9
1
1
1
1
1
1
1
1
1
1
0
Offer 10
0
0
0
0
0
0
0
0
0
0
0

and the following payoff matrix for ultimatum receivers:


Offer

0
1
2
3
4
5
6
7
8
9
10
Accept >= 0
0
1
2
3
4
5
6
7
8
9
10
Accept >= 1
0
1
2
3
4
5
6
7
8
9
10
Accept >= 2
0
0
2
3
4
5
6
7
8
9
10
Accept >= 3
0
0
0
3
4
5
6
7
8
9
10
Accept >= 4
0
0
0
0
4
5
6
7
8
9
10
Accept >= 5
0
0
0
0
0
5
6
7
8
9
10
Accept >= 6
0
0
0
0
0
0
6
7
8
9
10
Accept >= 7
0
0
0
0
0
0
0
7
8
9
10
Accept >= 8
0
0
0
0
0
0
0
0
8
9
10
Accept >= 9
0
0
0
0
0
0
0
0
0
9
10
Accept >= 10
0
0
0
0
0
0
0
0
0
0
10

In both cases there are 11 strategies.  If we think of each strategy as an integer, the only thing that changes between ultimatum proposers and ultimatum receivers is the interpretation of each strategy.

We begin by creating a new game consisting of 11 strategies.  Since we will later specify a payoff matrix for each person in the left and right population, we needn't worry about the fact that new games default to having all payoffs zero:
g = new Game(11);
SetGame(g);

Now define a custom payoff matrix for the ultimatum proposers:
proposer_payoffs = new PayoffMatrix(11);
for (i=0; i<11; i++) {
  for (j=0; j<11; j++) {
    if (i >= j)
      proposer_payoffs.setPayoff( i, j, 10-i );
    else
      proposer_payoffs.setPayoff( i, j, 0);
  }
}
;
and then define a custom payoff matrix for the ultimatum receivers:
receiver_payoffs = new PayoffMatrix(11);
for (i=0; i<11; i++) {
  for (j=0; j<11; j++) {
    if (i <= j)
      receiver_payoffs.setPayoff( i, j, j);
    else
      receiver_payoffs.setPayoff( i, j, 0);
  }
};
Create a population consisting of 30 individuals partitioned into two groups (subpopulations):
BipartiteGraph(30);
The resulting graph should look something like the following:



Make sure that all neighbors are added to the interaction neighborhood of the individuals:
AddNeighborsTo( InteractionNeighborhood );
Randomly wire the left subgroup to the right.  (The third argument to WireRandomly specifies the maximum number of wires to add to each member on the left.) The interaction neighborhoods of all left subgroup members will consist solely of members of the right subgroup, and vice versa.
WireRandomly( Left, Right, 2);
The network should look something like the following.  



In this case, there are some individuals on the right who do not have any members in their interaction neighborhood.  If this happens you can fix this by randomly wiring the right members to the left.
WireRandomly( Right, Left, 2);
This will give all individuals a nonempty interaction neighborhood:



Now tell the program to add new neighbors to an agent's update neighborhood:
AddNeighborsTo( UpdateNeighborhood );
Create the update neighbors for the left and right subgroups.  Wiring people in the left subgroup to the left subgroup gives the desired effect: each member of the left subgroup interacts with members of the right subgroup, and each member of the left subgroup updates (changes his strategy) based on the performance of members in the left subgroup.
WireRandomly( Left, Left, 2);
WireRandomly( Right, Right, 2);
At this point, the model should look something like the following:


According to the default settings, edges representing links of the update neighborhood are colored blue and edges representing links of the interaction neighborhood are colored black.

We now need to tell each subgroup which payoff matrix to use.  The following does the trick:
SetPayoffMatrixFor( Left, proposer_payoffs );
SetPayoffMatrixFor( Right, receiver_payoffs);

This command sets the payoff matrix for each member of the left subgroup to proposer_payoffs and the payoff matrix for each member of the right subgroup to receiver_payoffs.

Stepping the model forward by typing Alt+Z (or calling the command Evolve() in the shell) now runs a basic variant of Binmore's two-population model of the ultimatum game.  It should be clear how to modify the above commands to allow for larger cake sizes and populations.  Wrapping the code into a single function, as the file binmore.bsh illustrates, allows one to create and initialize a new model by simply typing
Binmore( N );
(where N is replaced by the desired population size).