diff --git a/MORE WORDS.md b/MORE WORDS.md index affe4eb..ea1d592 100644 --- a/MORE WORDS.md +++ b/MORE WORDS.md @@ -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? diff --git a/assets/evolution/evolution_intro.png b/assets/evolution/evolution_intro.png new file mode 100644 index 0000000..d26c2e3 Binary files /dev/null and b/assets/evolution/evolution_intro.png differ diff --git a/assets/tournament/connection.png b/assets/tournament/connection.png deleted file mode 100644 index e8fc78c..0000000 Binary files a/assets/tournament/connection.png and /dev/null differ diff --git a/assets/tournament/connection_flower.json b/assets/tournament/connection_flower.json new file mode 100644 index 0000000..c478eef --- /dev/null +++ b/assets/tournament/connection_flower.json @@ -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" +} +} diff --git a/assets/tournament/connection_flower.png b/assets/tournament/connection_flower.png new file mode 100644 index 0000000..650d413 Binary files /dev/null and b/assets/tournament/connection_flower.png differ diff --git a/assets/tournament/connection_gold.png b/assets/tournament/connection_gold.png deleted file mode 100644 index a3a0384..0000000 Binary files a/assets/tournament/connection_gold.png and /dev/null differ diff --git a/assets/tournament/score_small.png b/assets/tournament/score_small.png new file mode 100644 index 0000000..f202cc7 Binary files /dev/null and b/assets/tournament/score_small.png differ diff --git a/css/slides.css b/css/slides.css index 906f0da..9709694 100644 --- a/css/slides.css +++ b/css/slides.css @@ -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 ******/ /*************************/ diff --git a/index.html b/index.html index 79ba0fb..6c2c241 100644 --- a/index.html +++ b/index.html @@ -41,6 +41,7 @@ + @@ -85,7 +86,7 @@ window.onload = function(){ // First slide! //slideshow.nextSlide(); - slideshow.gotoSlide("iterated"); + slideshow.gotoSlide("evolution"); }); diff --git a/js/core/Button.js b/js/core/Button.js index 09a1047..6e23099 100644 --- a/js/core/Button.js +++ b/js/core/Button.js @@ -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(); diff --git a/js/core/ImageBox.js b/js/core/ImageBox.js new file mode 100644 index 0000000..dd17064 --- /dev/null +++ b/js/core/ImageBox.js @@ -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); }; + +} \ No newline at end of file diff --git a/js/core/TextBox.js b/js/core/TextBox.js index 815bd29..ff0a253 100644 --- a/js/core/TextBox.js +++ b/js/core/TextBox.js @@ -1,6 +1,3 @@ -/* - -*/ function TextBox(config){ var self = this; diff --git a/js/sims/PD.js b/js/sims/PD.js index 461e350..26ce058 100644 --- a/js/sims/PD.js +++ b/js/sims/PD.js @@ -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=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(); diff --git a/js/slides/2_Slides_Iterated.js b/js/slides/2_Slides_Iterated.js index 946b800..3a9c12a 100644 --- a/js/slides/2_Slides_Iterated.js +++ b/js/slides/2_Slides_Iterated.js @@ -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; diff --git a/js/slides/3_Slides_Tournament.js b/js/slides/3_Slides_Tournament.js index 18760c7..aacd042 100644 --- a/js/slides/3_Slides_Tournament.js +++ b/js/slides/3_Slides_Tournament.js @@ -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, ""+Words.get("label_"+_.answer)+""); + 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, ""+Words.get("label_"+charA)+""); + match_header = match_header.replace(/\[B\]/g, ""+Words.get("label_"+charB)+""); + words += match_header+"
"; + + // The rounds + words += Words.get("match_header_2")+"
"; + for(var i=0;i"; + } + words += "
"; + + // 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, ""+scoreA+""); + match_header = match_header.replace(/\[B\]/g, ""+scoreB+""); + words += match_header+"


"; + + // 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,20 +170,33 @@ SLIDES.push({ SLIDES.push({ onstart: function(self){ - // Words to the side - self.add({ - id:"text", type:"TextBox", - x:510, y:30, width:450, height:500, - text_id:"tournament_winner" - }); + var o = self.objects; + o.tournament.dehighlightAllConnections(); - // Button + // 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, ""+Words.get("label_"+_.answer)+""); + } + words += "

"; + words += Words.get("tournament_winner_3"); + o.text.setText(words); + + // Next... self.add({ - id:"button", type:"Button", x:385, y:466, - text_id:"tournament_teaser", fontSize:16, upperCase:false, - message:"slideshow/scratch" + id:"button", type:"Button", + x:510, y:430, size:"long", + text_id:"tournament_teaser", + message: "slideshow/scratch" }); + // FADE + _hide(o.text); _fadeIn(o.text, 100); + _hide(o.button); _fadeIn(o.button, 100+500); + }, onend: function(self){ self.clear(); diff --git a/js/slides/4_Slides_Evolution.js b/js/slides/4_Slides_Evolution.js index fcc4b4b..18e4f9b 100644 --- a/js/slides/4_Slides_Evolution.js +++ b/js/slides/4_Slides_Evolution.js @@ -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 + // 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.remove("bet_tft"); + self.remove("bet_all_c"); + self.remove("bet_all_d"); + } +}); + +// Result: ROUNDS ALL THE WAY 'TIL THE END +SLIDES.push({ + onstart: function(self){ + + var o = self.objects; + + // 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); + + // The tournament control buttons + var x = 510; + var y = 200; + var nextStep; + var textStep = 2; + // var textStep = 8; self.add({ - id:"button_step", type:"Button", - x:510, y:300, size:"short", - text_id:"button_step", - message: "tournament/step" + 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 }); - - // Button self.add({ - id:"button_next", type:"Button", - x:510, y:400, size:"short", - text_id:"label_next", + id:"step_3", type:"Button", x:x, y:y+70*2, + text_id: "label_reproduce_top_5", size:"long", onclick:function(){ - _.answer = "tft"; - publish("slideshow/scratch"); + 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){ - self.clear(); + unlisten(_); + self.remove("step_1"); + self.remove("step_2"); + self.remove("step_3"); } }); -// Result: First Round +// Result Explanation +SLIDES.push({ + onstart: function(self){ + + var o = self.objects; -// Result: Second Round + // What was your bet? + var response = Words.get("evo_9")+"

"+Words.get("evo_9_"+_.answer)+" "+Words.get("evo_9_end"); + o.text.setText(response); + _hide(o.text); _fadeIn(o.text, 100); -// Result: til the end... + // 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); -// Explanation + }, + 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 diff --git a/js/slides/6_Slides_Sandbox.js b/js/slides/6_Slides_Sandbox.js index 740d802..7cb1db1 100644 --- a/js/slides/6_Slides_Sandbox.js +++ b/js/slides/6_Slides_Sandbox.js @@ -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" }); diff --git a/lang/en.html b/lang/en.html index 1e695ce..8140f93 100644 --- a/lang/en.html +++ b/lang/en.html @@ -2,6 +2,8 @@ + +

During World War I, peace broke out.

@@ -117,6 +119,8 @@ But what happens if we can... + +

Now, let's play for real.
You'll be playing against 5 different opponents, each with their own "personality". @@ -182,15 +186,15 @@ 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. +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.

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. +If you cheat back, I'll act like Copycat. +If you never cheat back, I'll act like Always Cheat, to exploit you. Elementary, my dear Watson.

@@ -208,31 +212,93 @@ Now, what if these characters were to play...

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.

-Place your bets: who do you think will get the highest *total* score? +Who do you think will get the highest total score? +Think carefully about it, and then
+PLACE YOUR BETS: +

+ +

+Alright, you placed your bet on [CHAR]! +Let's go through the matches one by one, and see how the tournament plays out... +

+ +

+first match →

-next match +next match →

-

-COPYCAT! (Note: this play-style is also known in game theory as "Tit For Tat") -

+

+Match #[N]: [A] vs [B] +

+

+Rounds: +

+

+Total Scores: [A] vs [B] +

+ +

+  +

+

+Oh, by the way... +

+

+[trench live & let live stuff] +

+

+[trench live & let live stuff] +

+

+[trench live & let live stuff] +

+

+[trench live & let live stuff] +

+

+[trench live & let live stuff] +

+

+[trench live & let live stuff] +

+

+[trench live & let live stuff] +

+

+Anyway -- and the winner is... +

+ +

+(drumroll please...) → +

+ +

+COPYCAT! +

+

Congrats, you placed your bet on the right horse. +

+

+(Sorry, [CHAR].) +

+

+Copycat goes by many names. +The Golden Rule, reciprocal altruism, tit for tat, or... live and let live. +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 specific people (not just the same generic "enemy") over and over again -- +Copycat doesn't just win the battle, it wins the war.

-Sorry, //////. -

-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: -

-*Do unto others as you would have them do unto you.* ~Copycat -

-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. +But if things change a lot when you play multiple rounds of the same game, what if we play...

-

-...but does Copycat *always* win? → +...multiple tournaments?

@@ -241,13 +307,185 @@ And *that's* why "peace" broke out in the trenches of World War I. Each side was

+Now, let's let our population of players evolve over time. It's a 3-step dance: +

+

+1. PLAY A TOURNAMENT
+Let them all play against each other, and tally up their scores. +

+

+2. ELIMINATE LOSERS
+Get rid of the 5 worst players. (if there's a tie, pick randomly between them) +

+

+3. REPRODUCE WINNERS
+Clone the 5 best players. (if there's a tie, pick randomly between them) +

+ -

+...let's see this in action. →

-

-step +

+Say we start with the following population of players: +15 Always Cooperates, +5 Always Cheats, and +5 Copycats. +(We'll ignore Grudger & Detective for now) +

+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 first tournament? +

+ +

+Makes sense, Always Cooperate outnumbers everyone else right now... +

+

+Makes sense, Always Cheat has a lot of Always Cooperates to exploit... +

+

+Makes sense, Copycat won the tournament last time, why not again?... +

+

+Let's see if you're correct: +

+ +

+1) play tournament +

+

+2) eliminate bottom 5 +

+

+3) reproduce top 5 +

+ +

+Alas, Always Cooperate got eaten up by +Always Cheat, whose numbers have now increased by 5. +

+

+Sadly, you were correct! The Always Cheaters won this time, +and their numbers increased by 5. +

+

+Alas, Copycat did not win – but at least they didn't do as bad +as Always Cooperate, who got eaten up by Always Cheat, +whose numbers have now increased by 5. +

+

+But let's try a few more rounds of this... +

+ +

+Always Cheat is still growing, +at the expense of Always Cooperate... +

+ +

+And now, all the Always Cooperates are dead. +But, wait... +

+ +

+That's right: the Always Cheats became a victim of their own success! +They exploited the naive Always Cooperaters, +but once they ran out of them, they had to face the Copycats: +who are nice, but not naive. +

+ + + + +

+By simply copying the other player's moves, +Copycats can play nice with each other, +while Always Cheats just cheat themselves. +Not only that, but it also means Copycat +can give Always Cheat +a taste of their own medicine. +

+ +

+And so, as a result... +

+ +

+...Copycat inherits the earth. +

+

+So, although your bet was off -- the nice-but-naive Always Cooperaters +were doomed from the start -- in the end, a smart form of niceness prevailed, +and the Always Cheaters were squashed. +

+

+So, in the short run you were right - Always Cheat won the first few rounds, +but in the end, its exploitativeness was its downfall. +

+

+So, in the long run, you were right - Copycat wins! +Always Cheat may have won in the short run, +but its exploitativeness was its downfall. +

+

+This reminds me of a quote: +

+"We are punished by our sins, not for them."
+~ Elbert Hubbard +

+

+(oh, and by the way...) +

+ +

+(...this result is similar even if we put +Grudger & Detective back in:) +

+ +

+start the evolution process! +

+

+stop the evolution process +

+ + + + +

+(Note: occasionally, a few Grudgers may stick around, +because when all players except Grudger & Copycat +are eliminated, the two tie.) +

+So, it seems the math of game theory is telling us something: +that Copycat's philosophy, +"Do unto others as you would have them do unto you", may be not just a +moral truth, but also a mathematical truth. +However... +

+

+...there's a problem: → +

+ +

+There are jerks. Look around. +

+If Copycat 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? +

+A clue's in that sentence itself. "In this repeated game of trust." +So far we've only talked about change in the players: +what about a change in the game? +What could lead to... +

+

+...the evolution of distrust?

@@ -293,6 +531,11 @@ After each tournament, eliminate the bottom [N] player & reproduce the top [ In each round of a one-on-one game, there's a [N]% chance a player makes a mistake

+

+...once you're done playing around in Sandbox Mode, click: +

+ + @@ -322,40 +565,60 @@ blah blah blah blah
-

-Copycat -

+

Copycat

copycat

- -

-Always Cheat +

+ + + Copycat +

+ +

Always Cheat

cheater

- -

-Always Cooperate +

+ + + All Cheat +

+ +

Always Cooperate

cooperater

- -

-Grudger +

+ + + All Cooperate +

+ +

Grudger

grudger

- -

-Detective +

+ + + Grudger +

+ +

Detective

detective

+

+ + + Detective + +

Copykitten @@ -419,20 +682,8 @@ payoffs rules

-

-1) play tournament -

- -

-2) eliminate bottom 5 -

- -

-3) reproduce top 5 -

-

-next +next →