TOURNAMENT, EVOLUTION

This commit is contained in:
Nicky Case 2017-07-17 15:39:26 -04:00
parent e70f42c383
commit 8ff91b8135
19 changed files with 945 additions and 185 deletions

View file

@ -4,38 +4,3 @@ therefore, understand the conditions of trust, its mechanisms
---
And your total score is...
BIG NUMBER which is, wow, actually _impressively_ bad. // 8
which, uh, could be worse! // 9 to 21
which ain't bad! // 22 to 34
which is pretty good! // 34 to 48
which is actually _perfect_ // 49
which i have no idea how you accomplished
(the lowest & highest possible scores
are 8 and 49, respectively.)
So who were these strange characters you just played against?
COPYCAT:
Hello! I start with Cooperate, and afterwards, I just copy whatever you did in the last round. Meow
ALWAYS CHEAT:
_the strong shall eat the weak_
ALWAYS COOPERATE:
Let's be best friends! <3
GRUDGER:
Listen, stranger. I'll start cooperatin', and keep cooperation', but if y'all ever cheat me, I'LL CHEAT YOU BACK TIL THE END OF DAYS.
DETECTIVE:
First: I analyze you. I start: Cooperate, Cheat, Cooperate, Cooperate. If you cheat back, I'll act like Copycat. If you never cheat back, I'll act like Always Cheat, to exploit you. Elementary.
Now what if these characters were to play...
...against each other?

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

View file

@ -0,0 +1,43 @@
{"frames": {
"connection_flower0000":
{
"frame": {"x":10,"y":10,"w":401,"h":720},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":401,"h":720},
"sourceSize": {"w":401,"h":720}
},
"connection_flower0001":
{
"frame": {"x":421,"y":10,"w":401,"h":720},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":401,"h":720},
"sourceSize": {"w":401,"h":720}
},
"connection_flower0002":
{
"frame": {"x":10,"y":740,"w":401,"h":720},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":401,"h":720},
"sourceSize": {"w":401,"h":720}
},
"connection_flower0003":
{
"frame": {"x":421,"y":740,"w":401,"h":720},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":401,"h":720},
"sourceSize": {"w":401,"h":720}
}},
"meta": {
"app": "Adobe Animate",
"version": "15.2.0.66",
"image": "connection_flower.png",
"format": "RGBA8888",
"size": {"w":1024,"h":2048},
"scale": "1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

View file

@ -48,7 +48,6 @@ body{
}
#slideshow{
/*background: #bada55;*/
/*border: 1px solid rgba(0,0,0,0.2);*/
width:960px;
height:540px;
@ -134,7 +133,7 @@ body{
background-position: 0px -125px !important;
}
.button[deactivated=yes] #background{
background-position: 0px -250px;
background-position: 0px -250px !important;
}
.button[deactivated=yes] #text{
color: #CCCCCC;
@ -349,12 +348,50 @@ body{
.tft{ color:#4089DD; }
.all_d{ color:#52537F; }
.all_c{ color:#FF75FF; }
.grudge{ color:#C4A401; }
.prober{ color:#CC984C; }
.grudge{ color:#efc701; }
.prober{ color:#f6b24c; }
.tf2t{ color:#88A8CE; }
.pavlov{ color:#86C448; }
.random{ color:#FF5E5E; }
.icon{
width:25px; height:25px;
background: url(../assets/ui/sandbox_hats.png);
background-size: auto 100%;
display: inline-block;
position: relative;
top: 1px;
}
.icon_label{
display: inline-block;
font-size: 20px;
position: relative;
top: -3px;
}
.tft .icon{ background-position: 0 0; }
.all_d .icon{ background-position: -25px 0; }
.all_c .icon{ background-position: -50px 0; }
.grudge .icon{ background-position: -75px 0; }
.prober .icon{ background-position: -100px 0; }
.tf2t .icon{ background-position: -125px 0; }
.pavlov .icon{ background-position: -150px 0; }
.random .icon{ background-position: -175px 0; }
/*************************/
/******* MISC STUFF *******/
/*************************/
.score_small{
width:40px; height:40px;
background: url(../assets/tournament/score_small.png);
background-size: auto 100%;
display: inline-block;
}
.score_small[payoff=R]{ background-position: 0 0; }
.score_small[payoff=T]{ background-position: -40px 0; }
.score_small[payoff=S]{ background-position: -80px 0; }
.score_small[payoff=P]{ background-position: -120px 0; }
/*************************/
/***** SLIDE SELECT ******/
/*************************/

View file

@ -41,6 +41,7 @@
<script src="js/core/Slider.js"></script>
<script src="js/core/Scratcher.js"></script>
<script src="js/core/Background.js"></script>
<script src="js/core/ImageBox.js"></script>
<!-- Simulations -->
<script src="js/sims/Splash.js"></script>
@ -85,7 +86,7 @@ window.onload = function(){
// First slide!
//slideshow.nextSlide();
slideshow.gotoSlide("iterated");
slideshow.gotoSlide("evolution");
});

View file

@ -25,10 +25,6 @@ function Button(config){
// Customize DOM
button.style.left = config.x+"px";
button.style.top = config.y+"px";
if(config.fontSize){
text.style.fontSize = config.fontSize;
text.style.top = 14+(20-config.fontSize);
}
self.setText = function(text_id){
var words = Words.get(text_id);
if(config.uppercase) words = words.toUpperCase();

18
js/core/ImageBox.js Normal file
View file

@ -0,0 +1,18 @@
function ImageBox(config){
var self = this;
self.id = config.id;
// Create DOM
self.dom = new Image();
self.dom.className = "object";
self.dom.src = config.src;
// Customize
_configText(config, self.dom);
// Add & Remove
self.add = function(){ _add(self); };
self.remove = function(){ _remove(self); };
}

View file

@ -1,6 +1,3 @@
/*
*/
function TextBox(config){
var self = this;

View file

@ -2,8 +2,8 @@ var PEEP_METADATA = {
tft: {frame:0, color:"#4089DD"},
all_d: {frame:1, color:"#52537F"},
all_c: {frame:2, color:"#FF75FF"},
grudge: {frame:3, color:"#C4A401"},
prober: {frame:4, color:"#CC984C"},
grudge: {frame:3, color:"#efc701"},
prober: {frame:4, color:"#f6b24c"},
tf2t: {frame:5, color:"#88A8CE"},
pavlov: {frame:6, color:"#86C448"},
random: {frame:7, color:"#FF5E5E"}
@ -74,6 +74,9 @@ PD.playOneGame = function(playerA, playerB){
playerA.addPayoff(payoffs[0]);
playerB.addPayoff(payoffs[1]);
// Return the payoffs...
return payoffs;
};
PD.playRepeatedGame = function(playerA, playerB, turns){
@ -83,10 +86,21 @@ PD.playRepeatedGame = function(playerA, playerB, turns){
playerB.resetLogic();
// Play N turns
var scores = {
totalA:0,
totalB:0,
payoffs:[]
};
for(var i=0; i<turns; i++){
PD.playOneGame(playerA, playerB);
var p = PD.playOneGame(playerA, playerB);
scores.payoffs.push(p);
scores.totalA += p[0];
scores.totalB += p[1];
}
// Return the scores...
return scores;
};
PD.playOneTournament = function(agents, turns){

View file

@ -14,6 +14,8 @@ Tournament.resetGlobalVariables = function(){
{strategy:"random", count:5}
];
Tournament.FLOWER_CONNECTIONS = false;
publish("pd/defaultPayoffs");
PD.NOISE = 0;
@ -38,7 +40,8 @@ subscribe("rules/turns",function(value){
// REGULAR LOAD
Loader.addToManifest(Loader.manifest,{
tournament_peep: "assets/tournament/tournament_peep.json"
tournament_peep: "assets/tournament/tournament_peep.json",
connection_flower: "assets/tournament/connection_flower.json"
});
function Tournament(config){
@ -122,15 +125,18 @@ function Tournament(config){
// Connect all of 'em
for(var i=0; i<self.agents.length; i++){
var playerA = self.agents[i];
var flip = false;
for(var j=i+1; j<self.agents.length; j++){
var playerB = self.agents[j];
var connection = new TournamentConnection({
tournament: self,
from: playerA,
to: playerB
to: playerB,
flower_flip: flip
});
self.networkContainer.addChild(connection.graphics);
self.connections.push(connection);
flip = !flip;
}
}
@ -168,6 +174,48 @@ function Tournament(config){
self.reset();
////////////////////////////////////
// SHOW MATCHES ////////////////////
////////////////////////////////////
self.playMatch = function(number){
// GET OUR MATCH
var matches = [];
for(var a=0; a<self.agents.length; a++){
for(var b=a+1; b<self.agents.length; b++){
matches.push([self.agents[a], self.agents[b]]);
}
}
var match = matches[number];
// Highlight match
self.dehighlightAllConnections();
var connections = match[0].connections;
var connection = connections.filter(function(c){
if(c.from==match[0] && c.to==match[1]) return true;
if(c.from==match[1] && c.to==match[0]) return true;
return false;
})[0];
connection.highlight();
// Actually PLAY the game -- HACK: HARD-CODE 10 ROUNDS
var scores = PD.playRepeatedGame(match[0], match[1], 10);
// Return ALL this data...
return {
charA: match[0].strategyName,
charB: match[1].strategyName,
scoreA: scores.totalA,
scoreB: scores.totalB,
payoffs: scores.payoffs
}
};
self.dehighlightAllConnections = function(){
for(var i=0; i<self.connections.length; i++) self.connections[i].dehighlight();
};
////////////////////////////////////
// EVOLUTION ///////////////////////
////////////////////////////////////
@ -303,7 +351,7 @@ function Tournament(config){
_playIndex = 0;
_tweenTimer = 0;
self.STAGE = STAGE_REST;
// slideshow.objects._b2.activate(); // activate NEXT button!
publish("tournament/step/completed", ["play"]);
}
}
@ -314,8 +362,8 @@ function Tournament(config){
if(_tweenTimer==_s(0.3)){
_tweenTimer = 0;
self.STAGE = STAGE_REST;
publish("tournament/step/completed", ["eliminate"]);
}
// slideshow.objects._b3.activate(); // activate NEXT button!
}
// REPRODUCE!
@ -340,7 +388,7 @@ function Tournament(config){
if(_tweenTimer>=1){
_tweenTimer = 0;
self.STAGE = STAGE_REST;
// slideshow.objects._b1.activate(); // activate NEXT button!
publish("tournament/step/completed", ["reproduce"]);
}
}
@ -348,24 +396,16 @@ function Tournament(config){
});
// PLAY A TOURNAMENT
self.deactivateAllButtons = function(){
// slideshow.objects._b1.deactivate();
// slideshow.objects._b2.deactivate();
// slideshow.objects._b3.deactivate();
};
self._startPlay = function(){
self.STAGE=STAGE_PLAY;
// self.deactivateAllButtons();
};
listen(self, "tournament/play", self._startPlay);
self._startEliminate = function(){
self.STAGE=STAGE_ELIMINATE;
// self.deactivateAllButtons();
};
listen(self, "tournament/eliminate", self._startEliminate);
self._startReproduce = function(){
self.STAGE=STAGE_REPRODUCE;
// self.deactivateAllButtons();
};
listen(self, "tournament/reproduce", self._startReproduce);
@ -402,24 +442,46 @@ function TournamentConnection(config){
self.to.connections.push(self);
// Graphics!
var g = new PIXI.Container();
var gray = PIXI.Sprite.fromImage("assets/tournament/connection.png"); // TODO: PRELOAD
var gold = PIXI.Sprite.fromImage("assets/tournament/connection_gold.png"); // TODO: PRELOAD
gray.height = 1;
gold.height = 2;
gray.anchor.y = gold.anchor.y = 0.5;
g.addChild(gray);
g.addChild(gold);
var g;
if(Tournament.FLOWER_CONNECTIONS){
g = _makeMovieClip("connection_flower");
g.anchor.x = 0;
g.anchor.y = 0;
g.scale.set(0.5);
}else{
g = _makeMovieClip("connection");
g.anchor.x = 0;
g.anchor.y = 0.5;
g.height = 1;
}
self.graphics = g;
var _flowerLong = false;
var _updateFlower = function(highlight){
var frame = 0;
if(highlight) frame+=2;
if(_flowerLong) frame+=1;
g.gotoAndStop(frame);
};
if(config.flower_flip){
g.scale.y *= -1;
}
// Highlight or no?
self.highlight = function(){
gray.visible = false;
gold.visible = true;
if(Tournament.FLOWER_CONNECTIONS){
_updateFlower(true);
}else{
g.height = 3;
g.gotoAndStop(1);
}
};
self.dehighlight = function(){
gray.visible = true;
gold.visible = false;
if(Tournament.FLOWER_CONNECTIONS){
_updateFlower(false);
}else{
g.height = 1;
g.gotoAndStop(0);
}
};
self.dehighlight();
@ -435,9 +497,28 @@ function TournamentConnection(config){
g.x = f.x;
g.y = f.y;
g.rotation = a;
gray.width = gold.width = dist;
if(Tournament.FLOWER_CONNECTIONS){
if(dist<250){
_flowerLong = false;
if(config.flower_flip){
g.rotation = a+Math.TAU/10;
}else{
g.rotation = a-Math.TAU/10;
}
}else{
_flowerLong = true;
if(config.flower_flip){
g.rotation = a+Math.TAU/5;
}else{
g.rotation = a-Math.TAU/5;
}
}
_updateFlower();
}else{
g.rotation = a;
g.width = dist;
}
};
self.updateGraphics();

View file

@ -113,16 +113,16 @@ SLIDES.push({
_hide(o.info);
// ROUNDS
/*var ROUNDS = [
var ROUNDS = [
{id:"tft", num:1},
];*/ // FOR TESTING
var ROUNDS = [ // and min & max score...
]; // FOR TESTING
/*var ROUNDS = [ // and min & max score...
{id:"tft", num:5}, // min 3, max 11
{id:"all_d", num:4}, // min -4, max 0
{id:"all_c", num:4}, // min 8, max 12
{id:"grudge", num:5}, // min -1, max 11
{id:"prober", num:7} // min 2, max 15
]; // TOTAL... MIN 8, MAX 49
]; // TOTAL... MIN 8, MAX 49*/
ROUND_INDEX = 0;
ROUND_NUM = 0;

View file

@ -4,6 +4,7 @@ SLIDES.push({
onstart: function(self){
// Tournament
Tournament.resetGlobalVariables();
Tournament.INITIAL_AGENTS = [
{strategy:"tft", count:1},
{strategy:"all_d", count:1},
@ -11,6 +12,7 @@ SLIDES.push({
{strategy:"grudge", count:1},
{strategy:"prober", count:1}
];
Tournament.FLOWER_CONNECTIONS = true;
self.add({id:"tournament", type:"Tournament", x:-20, y:20});
// Words to the side
@ -21,37 +23,142 @@ SLIDES.push({
});
// Button
var _addButton = function(character, x, y){
(function(character, x, y){
self.add({
id:"bet_"+character, type:"Button", x:x, y:y,
text_id: "icon_"+character,
onclick:function(){
_.answer = character;
publish("slideshow/next");
}
});
})(character, x, y);
};
_addButton("tft", 510, 220+25);
_addButton("all_c", 730, 220+25);
_addButton("all_d", 510, 300+25);
_addButton("grudge", 730, 300+25);
_addButton("prober", 510, 380+25);
},
onend: function(self){
self.remove("bet_tft");
self.remove("bet_all_c");
self.remove("bet_all_d");
self.remove("bet_grudge");
self.remove("bet_prober");
}
});
// Alright, let's start!
SLIDES.push({
onstart: function(self){
var o = self.objects;
// What was your bet?
var tournament_intro = Words.get("tournament_intro");
tournament_intro = tournament_intro.replace(/\[CHAR\]/g, "<span class='"+_.answer+"'>"+Words.get("label_"+_.answer)+"</span>");
o.text.setText(tournament_intro);
_hide(o.text); _fadeIn(o.text, 100);
// "First Match" Button
self.add({
id:"button", type:"Button",
x:510, y:400,
text_id:"label_tft",
onclick:function(){
_.answer = "tft";
publish("slideshow/next");
}
x:510, y:130,
text_id:"first_match",
message: "slideshow/next"
});
_hide(o.button); _fadeIn(o.button, 100+500);
},
onend: function(self){
self.remove("text");
self.remove("button");
}
});
// go through it ONE BY ONE
// The matches... ONE BY ONE.
SLIDES.push({
onstart: function(self){
// Button
var o = self.objects;
var showTournament = function(num){
var words = "";
var match_header;
// PLAY MATCH
var matchData = o.tournament.playMatch(num);
var charA = matchData.charA;
var charB = matchData.charB;
var scoreA = matchData.scoreA
var scoreB = matchData.scoreB;
var roundPayoffs = matchData.payoffs;
// Match N: [A] versus [B]
match_header = Words.get("match_header_1");
match_header = match_header.replace(/\[N\]/g, (num+1)+"");
match_header = match_header.replace(/\[A\]/g, "<span class='"+charA+"'>"+Words.get("label_"+charA)+"</span>");
match_header = match_header.replace(/\[B\]/g, "<span class='"+charB+"'>"+Words.get("label_"+charB)+"</span>");
words += match_header+"<br>";
// The rounds
words += Words.get("match_header_2")+"<br>";
for(var i=0;i<roundPayoffs.length;i++){
var payoff = roundPayoffs[i][0];
if(payoff==PD.PAYOFFS.P) payoff="P"; // Punishment
if(payoff==PD.PAYOFFS.R) payoff="R"; // Reward
if(payoff==PD.PAYOFFS.S) payoff="S"; // Sucker
if(payoff==PD.PAYOFFS.T) payoff="T"; // Temptation
words += "<span class='score_small' payoff='"+payoff+"'></span>";
}
words += "<br>";
// The total scores
if(scoreA>0) scoreA="+"+scoreA;
if(scoreB>0) scoreB="+"+scoreB;
match_header = Words.get("match_header_3");
match_header = match_header.replace(/\[A\]/g, "<span class='"+charA+"'>"+scoreA+"</span>");
match_header = match_header.replace(/\[B\]/g, "<span class='"+charB+"'>"+scoreB+"</span>");
words += match_header+"<br><br><br>";
// Extra info
words += Words.get("tournament_"+(num+1));
// PUT IN THE WORDS
o.text.setText(words);
_hide(o.text); _fadeIn(o.text, 100);
// FINAL MATCH?
if(_matchNumber==9){
_switchButton();
}
};
// MATCH NUMBER!
_matchNumber = 0;
showTournament(_matchNumber);
// "Next Match" Button
self.add({
id:"button", type:"Button",
x:510, y:400,
x:510, y:420, size:"long",
text_id:"next_match",
onclick:function(){
_.answer = "tft";
publish("slideshow/next");
_matchNumber++;
showTournament(_matchNumber);
}
});
var _switchButton = function(){
o.button.setText("the_winner_is");
o.button.config.onclick = function(){
publish("slideshow/next");
};
};
_hide(o.button); _fadeIn(o.button, 100+500);
},
onend: function(self){
@ -63,19 +170,32 @@ SLIDES.push({
SLIDES.push({
onstart: function(self){
// Words to the side
var o = self.objects;
o.tournament.dehighlightAllConnections();
// WORDS
var words = "";
words += Words.get("tournament_winner_1");
if(_.answer=="tft"){
words += Words.get("tournament_winner_2_yay");
}else{
words += Words.get("tournament_winner_2_nay").replace(/\[CHAR\]/g, "<span class='"+_.answer+"'>"+Words.get("label_"+_.answer)+"</span>");
}
words += "<br><br>";
words += Words.get("tournament_winner_3");
o.text.setText(words);
// Next...
self.add({
id:"text", type:"TextBox",
x:510, y:30, width:450, height:500,
text_id:"tournament_winner"
id:"button", type:"Button",
x:510, y:430, size:"long",
text_id:"tournament_teaser",
message: "slideshow/scratch"
});
// Button
self.add({
id:"button", type:"Button", x:385, y:466,
text_id:"tournament_teaser", fontSize:16, upperCase:false,
message:"slideshow/scratch"
});
// FADE
_hide(o.text); _fadeIn(o.text, 100);
_hide(o.button); _fadeIn(o.button, 100+500);
},
onend: function(self){

View file

@ -3,17 +3,44 @@ SLIDES.push({
id: "evolution",
onstart: function(self){
// Words to the side
// WORDS
self.add({
id:"text", type:"TextBox",
x:510, y:30, width:450, height:500,
id:"text1", type:"TextBox",
x:0, y:20, width:774, height:42,
text_id:"evolution_intro"
});
self.add({
id:"text2", type:"TextBox",
x:0, y:235, width:287, height:117, align:"center",
text_id:"evolution_intro_1"
});
self.add({
id:"text3", type:"TextBox",
x:336, y:235, width:287, height:117, align:"center",
text_id:"evolution_intro_2"
});
self.add({
id:"text4", type:"TextBox",
x:669, y:235, width:287, height:117, align:"center",
text_id:"evolution_intro_3"
});
self.add({
id:"text5", type:"TextBox",
x:132, y:370, width:817, height:95, align:"right",
text_id:"evolution_intro_footer"
});
// IMAGE
self.add({
id:"img", type:"ImageBox",
src: "assets/evolution/evolution_intro.png",
x:0, y:60, width:960, height:170
});
// Button
self.add({
id:"button", type:"Button", x:385, y:466,
text_id:"evolution_intro_button", fontSize:16, upperCase:false,
id:"button", type:"Button", x:615, y:466,
text_id:"evolution_intro_button", size:"long",
message:"slideshow/scratch"
});
@ -28,6 +55,7 @@ SLIDES.push({
onstart: function(self){
// Tournament
Tournament.resetGlobalVariables();
Tournament.INITIAL_AGENTS = [
{strategy:"all_c", count:15},
{strategy:"all_d", count:5},
@ -39,45 +67,249 @@ SLIDES.push({
self.add({
id:"text", type:"TextBox",
x:510, y:30, width:450, height:500,
text_id:"evo_bets"
text_id:"evo_1"
});
// Button
self.add({
id:"button_step", type:"Button",
x:510, y:300, size:"short",
text_id:"button_step",
message: "tournament/step"
});
// Button
self.add({
id:"button_next", type:"Button",
x:510, y:400, size:"short",
text_id:"label_next",
onclick:function(){
_.answer = "tft";
publish("slideshow/scratch");
}
});
// BETS
var _addButton = function(character, x, y){
(function(character, x, y){
self.add({
id:"bet_"+character, type:"Button", x:x, y:y,
text_id: "icon_"+character,
onclick:function(){
_.answer = character;
publish("slideshow/next");
}
});
})(character, x, y);
};
_addButton("all_c", 510, 295);
_addButton("all_d", 510, 295+70);
_addButton("tft", 510, 295+70*2);
},
onend: function(self){
self.clear();
self.remove("bet_tft");
self.remove("bet_all_c");
self.remove("bet_all_d");
}
});
// Result: First Round
// Result: ROUNDS ALL THE WAY 'TIL THE END
SLIDES.push({
onstart: function(self){
// Result: Second Round
var o = self.objects;
// Result: til the end...
// What was your bet?
var response = Words.get("evo_2_"+_.answer)+" "+Words.get("evo_2");
o.text.setText(response);
_hide(o.text); _fadeIn(o.text, 100);
// Explanation
// The tournament control buttons
var x = 510;
var y = 200;
var nextStep;
var textStep = 2;
// var textStep = 8;
self.add({
id:"step_1", type:"Button", x:x, y:y,
text_id: "label_play_tournament", size:"long",
onclick:function(){
o.step_1.deactivate();
nextStep = o.step_2;
publish("tournament/play");
}
});
self.add({
id:"step_2", type:"Button", x:x, y:y+70,
text_id: "label_eliminate_bottom_5", size:"long",
onclick:function(){
o.step_2.deactivate();
nextStep = o.step_3;
publish("tournament/eliminate");
},
active: false
});
self.add({
id:"step_3", type:"Button", x:x, y:y+70*2,
text_id: "label_reproduce_top_5", size:"long",
onclick:function(){
o.step_3.deactivate();
nextStep = o.step_1;
publish("tournament/reproduce");
},
active: false
});
listen(_, "tournament/step/completed", function(step){
nextStep.activate();
if(step=="reproduce"){
textStep++;
var response;
if(textStep<9){
if(textStep==3){
response = Words.get("evo_3_"+_.answer)+" "+Words.get("evo_3");
}else{
response = Words.get("evo_"+textStep);
}
o.text.setText(response);
_hide(o.text); _fadeIn(o.text, 100);
_showButtons();
}else{
publish("slideshow/next");
}
}
});
var _showButtons = function(){
_hide(o.step_1); _fadeIn(o.step_1, 500);
_hide(o.step_2); _fadeIn(o.step_2, 600);
_hide(o.step_3); _fadeIn(o.step_3, 700);
};
_showButtons();
},
onend: function(self){
unlisten(_);
self.remove("step_1");
self.remove("step_2");
self.remove("step_3");
}
});
// Result Explanation
SLIDES.push({
onstart: function(self){
var o = self.objects;
// What was your bet?
var response = Words.get("evo_9")+"<br><br>"+Words.get("evo_9_"+_.answer)+" "+Words.get("evo_9_end");
o.text.setText(response);
_hide(o.text); _fadeIn(o.text, 100);
// Oh by the way...
self.add({
id:"button", type:"Button", x:510, y:320,
text_id:"evo_9_btn", size:"long",
message: "slideshow/next"
});
_hide(o.button); _fadeIn(o.button, 400);
},
onend: function(self){
self.remove("button");
}
});
// (Yup, even w Grudgers & Detectives)
SLIDES.push({
onstart: function(self){
// Tournament
var o = self.objects;
Tournament.resetGlobalVariables();
Tournament.INITIAL_AGENTS = [
{strategy:"all_c", count:5},
{strategy:"all_d", count:5},
{strategy:"tft", count:5},
{strategy:"grudge", count:5},
{strategy:"prober", count:6}
];
o.tournament.reset();
_hide(o.tournament); _fadeIn(o.tournament, 10);
// The same with grudger & detetive!
o.text.setTextID("evo_10");
_hide(o.text); _fadeIn(o.text, 400);
// Button: start/stop
var isPlaying = false;
self.add({
id:"autoplay", type:"Button", x:510, y:100,
text_id:"evo_autoplay", size:"long",
onclick: function(){
if(!isPlaying){
o.autoplay.setText("evo_autoplay_stop");
publish("tournament/autoplay/start");
isPlaying = true;
}else{
o.autoplay.setText("evo_autoplay");
publish("tournament/autoplay/stop");
isPlaying = false;
}
}
});
_hide(o.autoplay); _fadeIn(o.autoplay, 600);
// Listen...
var step = 0;
listen(_, "tournament/step/completed", function(aahhhh){
step++;
if(step==13){
_goOn();
}
});
var _goOn = function(){
// Text followup (hidden)
self.add({
id:"text2", type:"TextBox",
x:510, y:180, width:450, height:500,
text_id:"evo_10_followup"
});
_hide(o.text2); _fadeIn(o.text2, 400);
// Button: next (hidden)
self.add({
id:"next", type:"Button", x:510, y:450,
text_id:"evo_10_btn", size:"long",
message: "slideshow/next"
});
_hide(o.next); _fadeIn(o.next, 600);
};
},
onend: function(self){
unlisten(_);
self.remove("autoplay");
self.remove("text2");
self.remove("next");
}
});
// Problem 1: Number of interactions
SLIDES.push({
onstart: function(self){
var o = self.objects;
// Oh no
Tournament.resetGlobalVariables();
Tournament.INITIAL_AGENTS = [
{strategy:"all_d", count:24},
{strategy:"tft", count:1}
];
o.tournament.reset();
// Text
o.text.setTextID("evo_11");
_hide(o.text); _fadeIn(o.text, 200);
// Next
self.add({
id:"next", type:"Button", x:510, y:415,
text_id:"evo_11_btn", size:"long",
message: "slideshow/next"
});
_hide(o.next); _fadeIn(o.next, 500);
},
onend: function(self){
self.remove("text");
self.remove("next");
}
});
// Problem 2: Payoffs

View file

@ -10,10 +10,15 @@ SLIDES.push({
// Screw it, just ALL of the Sandbox UI
self.add({id:"sandbox", type:"SandboxUI"});
// Button for next...
// Label & Button for next...
self.add({
id:"label_next", type:"TextBox",
x:14, y:481, width:800, align:"right",
text_id: "sandbox_end"
});
self.add({
id:"button_next", type:"Button",
x:510, y:500,
x:831, y:465, size:"short",
text_id:"label_next",
message: "slideshow/scratch"
});

View file

@ -2,6 +2,8 @@
<!-- - - - - - INTRO! - - - - - - - - -->
<!-- - - - - - - - - - - - - - - - - -->
<!-- TODO: Focus ONLY on social trust, not governments -->
<p id="intro">
During World War I, peace broke out.
<br><br>
@ -117,6 +119,8 @@ But what happens if we can...
<!-- - - - - - ITERATED - - - - - - - -->
<!-- - - - - - - - - - - - - - - - - -->
<!-- TO DO: WEAVE IN MORE ABOUT TRENCHES. "CHOOSE WISELY" -->
<p id="iterated_intro_top">
<b>Now, let's play for real.</b><br>
You'll be playing against 5 different opponents, each with their own "personality".
@ -182,15 +186,15 @@ Let's be best friends! &lt;3
<p id="character_grudge">
<b>GRUDGER:</b>
Listen, stranger. I'll start cooperatin', and keep cooperation',
but if y'all ever cheat me, I'LL CHEAT YOU BACK TIL THE END OF DAYS.
Listen, pardner. I'll start cooperatin', and keep cooperation',
but if y'all ever cheat me, I'LL CHEAT YOU BACK 'TIL THE END OF TARNATION.
</p>
<p id="character_prober">
<b>DETECTIVE:</b>
First: I analyze you. I start: Cooperate, Cheat, Cooperate, Cooperate.
If you cheat back, I'll act like Copycat.
If you never cheat back, I'll act like Always Cheat, to exploit you.
If you cheat back, I'll act like <span class="tft">Copycat</span>.
If you never cheat back, I'll act like <span class="all_d">Always Cheat</span>, to exploit you.
Elementary, my dear Watson.
</p>
@ -208,31 +212,93 @@ Now, what if these characters were to play...
<p id="place_your_bets">
It's tournament time!
These five characters will now play against each other 10 paired games, 10 rounds per game.
Each character will now play against every other character:
that's 10 paired matches, and 10 rounds per match.
<br><br>
Place your bets: who do you think will get the highest *total* score?
Who do you think will get the highest <i>total</i> score?
Think carefully about it, and then<br>
<b>PLACE YOUR BETS:</b>
</p>
<p id="tournament_intro">
Alright, you placed your bet on [CHAR]!
Let's go through the matches one by one, and see how the tournament plays out...
</p>
<p id="first_match">
first match &rarr;
</p>
<p id="next_match">
next match
next match &rarr;
</p>
<p id="tournament_winner">
COPYCAT! (Note: this play-style is also known in game theory as "Tit For Tat")
<br><br>
<p id="match_header_1">
<b>Match #[N]:</b> [A] vs [B]
</p>
<p id="match_header_2">
<b>Rounds:</b>
</p>
<p id="match_header_3">
<b>Total Scores:</b> [A] vs [B]
</p>
<p id="tournament_1">
&nbsp;
</p>
<p id="tournament_2">
Oh, by the way...
</p>
<p id="tournament_3">
[trench live &amp; let live stuff]
</p>
<p id="tournament_4">
[trench live &amp; let live stuff]
</p>
<p id="tournament_5">
[trench live &amp; let live stuff]
</p>
<p id="tournament_6">
[trench live &amp; let live stuff]
</p>
<p id="tournament_7">
[trench live &amp; let live stuff]
</p>
<p id="tournament_8">
[trench live &amp; let live stuff]
</p>
<p id="tournament_9">
[trench live &amp; let live stuff]
</p>
<p id="tournament_10">
Anyway -- and the winner is...
</p>
<p id="the_winner_is">
(drumroll please...) &rarr;
</p>
<p id="tournament_winner_1">
<b class="tft">COPYCAT!</b>
</p>
<p id="tournament_winner_2_yay">
Congrats, you placed your bet on the right horse.
<br><br>
Sorry, //////.
<br><br>
Now, here's the strange thing: Copycat can _never_ beat another player in the trust game (because it never tries to take advantage of others), it can only ever do _as well as_ the other player. And yet overall, Copycat wins! This, despite being simpler than Detective, nicer than Always Cheat, and more forgiving than Grudger. It almost seems to imply that the Golden Rule is not just a moral truth, but a *mathematical* truth:
<br><br>
*Do unto others as you would have them do unto you.* ~Copycat
<br><br>
And *that's* why "peace" broke out in the trenches of World War I. Each side was playing a deadly game of trust with each other, but because the nature of trench warfare means they have to face the same group of soldiers over and over again, that allowed a Copycat-like strategy the unspoken law of "live and let live" to evolve.
</p>
<p id="tournament_winner_2_nay">
(Sorry, [CHAR].)
</p>
<p id="tournament_winner_3">
<span class="tft">Copycat</span> goes by many names.
The Golden Rule, reciprocal altruism, tit for tat, or... <i>live and let live.</i>
That's why "peace" could emerge in the trenches of World War I:
when you're forced to play the same game with the
same <i>specific people</i> (not just the same generic "enemy") over and over again --
<span class="tft">Copycat</span> doesn't just win the battle, it wins the war.
<br><br>
But if things change a lot when you play multiple rounds of the same game, what if we play...
</p>
<p id="tournament_teaser">
...but does Copycat *always* win? &rarr;
...multiple <i>tournaments?</i> &rarr;
</p>
@ -241,13 +307,185 @@ And *that's* why "peace" broke out in the trenches of World War I. Each side was
<!-- - - - - - - - - - - - - - - - - -->
<p id="evolution_intro">
Now, let's let our population of players <i>evolve over time</i>. It's a 3-step dance:
</p>
<p id="evolution_intro_1">
<b>1. PLAY A TOURNAMENT</b><br>
Let them all play against each other, and tally up their scores.
</p>
<p id="evolution_intro_2">
<b>2. ELIMINATE LOSERS</b><br>
Get rid of the 5 worst players. (if there's a tie, pick randomly between them)
</p>
<p id="evolution_intro_3">
<b>3. REPRODUCE WINNERS</b><br>
Clone the 5 best players. (if there's a tie, pick randomly between them)
</p>
<p id="evolution_intro_footer">
...and REPEAT, for as long as you'd like.
Note: you don't have to wait for people to literally die &amp; reproduce for culture to evolve --
all that's needed is that "unsuccessful" behaviors go away, and "successful" behaviors are imitated.
So now...
</p>
<p id="evolution_intro_button">
...let's see this in action. &rarr;
</p>
<p id="button_step">
step
<p id="evo_1">
Say we start with the following population of players:
<span class="all_c">15 Always Cooperates</span>,
<span class="all_d">5 Always Cheats</span>, and
<span class="tft">5 Copycats</span>.
(We'll ignore <span class="grudge">Grudger</span> &amp; <span class="prober">Detective</span> for now)
<br><br>
We're going to do the tournament-eliminate-reproduce dance a dozen times or so.
Let's make another bet! Who do you think will win the <i>first</i> tournament?
</p>
<p id="evo_2_all_c">
Makes sense, <span class="all_c">Always Cooperate</span> outnumbers everyone else right now...
</p>
<p id="evo_2_all_d">
Makes sense, <span class="all_d">Always Cheat</span> has a lot of <span class="all_c">Always Cooperates</span> to exploit...
</p>
<p id="evo_2_tft">
Makes sense, <span class="tft">Copycat</span> won the tournament last time, why not again?...
</p>
<p id="evo_2">
Let's see if you're correct:
</p>
<p id="label_play_tournament">
1) play tournament
</p>
<p id="label_eliminate_bottom_5">
2) eliminate bottom 5
</p>
<p id="label_reproduce_top_5">
3) reproduce top 5
</p>
<p id="evo_3_all_c">
Alas, <span class="all_c">Always Cooperate</span> got eaten up by
<span class="all_d">Always Cheat</span>, whose numbers have now increased by 5.
</p>
<p id="evo_3_all_d">
Sadly, you were correct! The <span class="all_d">Always Cheaters</span> won this time,
and their numbers increased by 5.
</p>
<p id="evo_3_tft">
Alas, <span class="tft">Copycat</span> did not win but at least they didn't do as bad
as <span class="all_c">Always Cooperate</span>, who got eaten up by <span class="all_d">Always Cheat</span>,
whose numbers have now increased by 5.
</p>
<p id="evo_3">
But let's try a few more rounds of this...
</p>
<p id="evo_4">
<span class="all_d">Always Cheat</span> is still growing,
at the expense of <span class="all_c">Always Cooperate</span>...
</p>
<p id="evo_5">
And now, all the <span class="all_c">Always Cooperates</span> are dead.
But, wait...
</p>
<p id="evo_6">
That's right: the <span class="all_d">Always Cheats</span> became a victim of their own success!
They exploited the naive <span class="all_c">Always Cooperaters</span>,
but once they ran out of them, they had to face the <span class="tft">Copycats</span>:
who <i>are</i> nice, but not naive.
</p>
<!-- TODO: Freeman-Dyson???? -->
<!-- TODO: (other strategies will be introduced later) -->
<p id="evo_7">
By simply copying the other player's moves,
<span class="tft">Copycats</span> can play nice with each other,
while <span class="all_d">Always Cheats</span> just cheat themselves.
Not only that, but it also means <span class="tft">Copycat</span>
can give <span class="all_d">Always Cheat</span>
a taste of their own medicine.
</p>
<p id="evo_8">
And so, as a result...
</p>
<p id="evo_9">
...<span class="tft">Copycat</span> inherits the earth.
</p>
<p id="evo_9_all_c">
So, although your bet was off -- the nice-but-naive <span class="all_c">Always Cooperaters</span>
were doomed from the start -- in the end, a <i>smart</i> form of niceness prevailed,
and the <span class="all_d">Always Cheaters</span> were squashed.
</p>
<p id="evo_9_all_d">
So, in the short run you were right - <span class="all_d">Always Cheat</span> won the first few rounds,
but in the end, its exploitativeness was its downfall.
</p>
<p id="evo_9_tft">
So, in the long run, you were right - <span class="tft">Copycat</span> wins!
<span class="all_d">Always Cheat</span> may have won in the short run,
but its exploitativeness was its downfall.
</p>
<p id="evo_9_end">
This reminds me of a quote:
<br><br>
<i>"We are punished by our sins, not for them."</i><br>
~ Elbert Hubbard
</p>
<p id="evo_9_btn">
(oh, and by the way...)
</p>
<p id="evo_10">
(...this result is similar even if we put
<span class="grudge">Grudger</span> &amp; <span class="prober">Detective</span> back in:)
</p>
<p id="evo_autoplay">
start the evolution process!
</p>
<p id="evo_autoplay_stop">
stop the evolution process
</p>
<!-- More reference to game theory earlier? -->
<!-- TODO: More "me" and "I"??? -->
<p id="evo_10_followup">
(Note: occasionally, a few <span class="grudge">Grudgers</span> may stick around,
because when all players except <span class="grudge">Grudger</span> &amp; <span class="tft">Copycat</span>
are eliminated, the two tie.)
<br><br>
So, it seems the math of game theory is telling us something:
that <span class="tft">Copycat's</span> philosophy,
"Do unto others as you would have them do unto you", may be not just a
<i>moral</i> truth, but also a <i>mathematical</i> truth.
However...
</p>
<p id="evo_10_btn">
...there's a problem: &rarr;
</p>
<p id="evo_11">
There are jerks. Look around.
<br><br>
If <span class="tft">Copycat</span> is the strategy in this repeated game of trust that's so powerful --
that even soldiers in the trenches of World War I independently "evolved" a similar strategy --
why, then, are there so many un-trusting, un-trustworthy people around?
<br><br>
A clue's in that sentence itself. "In <i>this</i> repeated game of trust."
So far we've only talked about change in the players:
what about <i>a change in the game?</i>
What could lead to...
</p>
<p id="evo_11_btn">
...the evolution of <i>distrust?</i>
</p>
<!-- - - - - - - - - - - - - - - - - -->
@ -293,6 +531,11 @@ After each tournament, eliminate the bottom [N] player &amp; reproduce the top [
In each round of a one-on-one game, there's a [N]% chance a player makes a mistake
</p>
<p id="sandbox_end">
...once you're done playing around in Sandbox Mode, click:
</p>
<!-- - - - - - - - - - - - - - - - - -->
<!-- - - - - CONCLUSION! - - - - - - -->
@ -322,40 +565,60 @@ blah blah blah blah<br>
<!-- - - - - THE PLAYERS - - - - - - -->
<!-- - - - - - - - - - - - - - - - - -->
<p id="label_tft">
Copycat
</p>
<p id="label_tft">Copycat</p>
<p id="label_short_tft">
copycat
</p>
<p id="label_all_d">
Always Cheat
<p id="icon_tft">
<span class="tft">
<span class="icon"></span>
<span class="icon_label">Copycat</span>
</span>
</p>
<p id="label_all_d">Always Cheat</p>
<p id="label_short_all_d">
cheater
</p>
<p id="label_all_c">
Always Cooperate
<p id="icon_all_d">
<span class="all_d">
<span class="icon"></span>
<span class="icon_label">All Cheat</span>
</span>
</p>
<p id="label_all_c">Always Cooperate</p>
<p id="label_short_all_c">
cooperater
</p>
<p id="label_grudge">
Grudger
<p id="icon_all_c">
<span class="all_c">
<span class="icon"></span>
<span class="icon_label">All Cooperate</span>
</span>
</p>
<p id="label_grudge">Grudger</p>
<p id="label_short_grudge">
grudger
</p>
<p id="label_prober">
Detective
<p id="icon_grudge">
<span class="grudge">
<span class="icon"></span>
<span class="icon_label">Grudger</span>
</span>
</p>
<p id="label_prober">Detective</p>
<p id="label_short_prober">
detective
</p>
<p id="icon_prober">
<span class="prober">
<span class="icon"></span>
<span class="icon_label">Detective</span>
</span>
</p>
<p id="label_tf2t">
Copykitten
@ -419,20 +682,8 @@ payoffs
rules
</p>
<p id="label_play_tournament">
1) play tournament
</p>
<p id="label_eliminate_bottom_5">
2) eliminate bottom 5
</p>
<p id="label_reproduce_top_5">
3) reproduce top 5
</p>
<p id="label_next">
next
next &rarr;
</p>