THE WHOLE SANDBOX HELL YEAH
This commit is contained in:
parent
f918fe2275
commit
0ff92634df
11 changed files with 452 additions and 33 deletions
4
TODO.md
4
TODO.md
|
@ -13,4 +13,6 @@ MINOR SHTUFF
|
|||
- Word box class less annoying
|
||||
- Refactoring, ugh
|
||||
- Draw: Pavlov, TF2T, Random
|
||||
- a better handwritten font, with REAL bold & italics???
|
||||
- a better handwritten font, with REAL bold & italics???
|
||||
- rename Tit For Tat, so it FEELS nicer??? also block peeps who already know the answer... // Copycat Copykitten
|
||||
- rename all of 'em, really?
|
BIN
assets/sandbox_hats.png
Normal file
BIN
assets/sandbox_hats.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
assets/slider_bg.png
Normal file
BIN
assets/slider_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 632 B |
BIN
assets/slider_knob.png
Normal file
BIN
assets/slider_knob.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -74,6 +74,10 @@ body{
|
|||
|
||||
.button{
|
||||
z-index: 0;
|
||||
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||
-moz-user-select: none; /* Firefox all */
|
||||
-ms-user-select: none; /* IE 10+ */
|
||||
user-select: none;
|
||||
}
|
||||
.button #background{
|
||||
position: absolute;
|
||||
|
@ -177,6 +181,44 @@ body{
|
|||
.incdec > .incdec_control[arrow=down]{ bottom:-35px; background-position:-40px 0px; }
|
||||
.incdec > .incdec_control[arrow=down]:hover{ background-position:-60px 0px; }
|
||||
|
||||
.slider{
|
||||
position: absolute;
|
||||
height: 40px;
|
||||
}
|
||||
.slider > div{
|
||||
position: absolute;
|
||||
}
|
||||
.slider > .slider_bg{
|
||||
top:0;
|
||||
width:100%; height:30px;
|
||||
background: url(../assets/slider_bg.png);
|
||||
background-size: auto 100%;
|
||||
}
|
||||
.slider > .slider_knob{
|
||||
top:0;
|
||||
width:30px; height:30px;
|
||||
background: url(../assets/slider_knob.png);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.sandbox_pop{
|
||||
position: absolute;
|
||||
}
|
||||
.sandbox_pop>div{
|
||||
position: absolute;
|
||||
}
|
||||
.sandbox_pop_icon{
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: url(../assets/sandbox_hats.png);
|
||||
background-size: auto 100%;
|
||||
}
|
||||
.sandbox_pop_label{
|
||||
font-size: 18px;
|
||||
width: 150px;
|
||||
top: 8px;
|
||||
left: 50px;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/***** SLIDE SELECT ******/
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<script src="js/core/TextBox.js"></script>
|
||||
<script src="js/core/Words.js"></script>
|
||||
<script src="js/core/IncDecNumber.js"></script>
|
||||
<script src="js/core/Slider.js"></script>
|
||||
|
||||
<!-- Simulations -->
|
||||
<script src="js/sims/PD.js"></script>
|
||||
|
|
113
js/core/Slider.js
Normal file
113
js/core/Slider.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
/**************************************
|
||||
{
|
||||
x:0, y:0, width:433,
|
||||
min:1, max:25, step:1,
|
||||
message: "rules/turns"
|
||||
}
|
||||
**************************************/
|
||||
function Slider(config){
|
||||
|
||||
var self = this;
|
||||
self.id = config.id;
|
||||
|
||||
// Create DOM
|
||||
var dom = document.createElement("div");
|
||||
dom.className = "slider";
|
||||
dom.style.left = config.x+"px";
|
||||
dom.style.top = config.y+"px";
|
||||
dom.style.width = config.width+"px";
|
||||
self.dom = dom;
|
||||
|
||||
// Background
|
||||
var bg = document.createElement("div");
|
||||
bg.className = "slider_bg";
|
||||
dom.appendChild(bg);
|
||||
|
||||
// Knob
|
||||
var knob = document.createElement("div");
|
||||
knob.className = "slider_knob";
|
||||
dom.appendChild(knob);
|
||||
|
||||
// Set value
|
||||
self.value = 0;
|
||||
var _paramToValue = function(param){
|
||||
var value = config.min + (config.max-config.min)*param;
|
||||
value = Math.round(value/config.step)*config.step;
|
||||
return value;
|
||||
};
|
||||
var _valueToParam = function(value){
|
||||
var param = (value-config.min)/(config.max-config.min); // to (0-1)
|
||||
return param;
|
||||
};
|
||||
self.setParam = function(param){
|
||||
|
||||
// Bounds
|
||||
var value = config.min + (config.max-config.min)*param;
|
||||
value = Math.round(value/config.step)*config.step;
|
||||
self.value = value;
|
||||
|
||||
// DOM
|
||||
knob.style.left = self.value*config.width-15;
|
||||
|
||||
};
|
||||
self.setValue = function(value){
|
||||
|
||||
// Set
|
||||
self.value = value;
|
||||
|
||||
// DOM with param
|
||||
var param = _valueToParam(self.value);
|
||||
knob.style.left = param*(config.width-30);
|
||||
|
||||
};
|
||||
if(config.message) subscribe(config.message, self.setValue);
|
||||
|
||||
// Mouse events
|
||||
var _isDragging = false;
|
||||
var _offsetX = 0;
|
||||
var _mouseToParam = function(event){
|
||||
|
||||
// Mouse to Param to Value
|
||||
var param = (event.clientX - _offsetX - dom.getBoundingClientRect().left - 8)/(config.width-30);
|
||||
if(param<0) param=0;
|
||||
if(param>1) param=1;
|
||||
var value = _paramToValue(param);
|
||||
|
||||
// Publish these changes! (only if ACTUALLY changed)
|
||||
if(self.value != value){
|
||||
if(config.message) publish(config.message, [value]);
|
||||
if(config.onchange) config.onchange(value);
|
||||
}
|
||||
|
||||
};
|
||||
dom.addEventListener("mousedown",function(event){
|
||||
if(config.onselect) config.onselect();
|
||||
_mouseToParam(event);
|
||||
_isDragging = true;
|
||||
_offsetX = 0;
|
||||
},false);
|
||||
knob.addEventListener("mousedown",function(event){
|
||||
_isDragging = true;
|
||||
if(config.onselect) config.onselect();
|
||||
_offsetX = event.clientX - knob.getBoundingClientRect().left;
|
||||
},false);
|
||||
window.addEventListener("mousemove",function(event){
|
||||
if(_isDragging) _mouseToParam(event);
|
||||
},false);
|
||||
window.addEventListener("mouseup",function(){
|
||||
_isDragging = false;
|
||||
},false);
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
// Add...
|
||||
self.add = function(INSTANT){
|
||||
return _add(self, INSTANT);
|
||||
};
|
||||
|
||||
// Remove...
|
||||
self.remove = function(INSTANT){
|
||||
return _remove(self, INSTANT);
|
||||
};
|
||||
|
||||
}
|
|
@ -30,6 +30,9 @@ subscribe("pd/defaultPayoffs", function(){
|
|||
});
|
||||
|
||||
PD.NOISE = 0;
|
||||
subscribe("rules/noise",function(value){
|
||||
PD.NOISE = value;
|
||||
});
|
||||
|
||||
PD.getPayoffs = function(move1, move2){
|
||||
var payoffs = PD.PAYOFFS;
|
||||
|
|
|
@ -97,6 +97,193 @@ function SandboxUI(config){
|
|||
// PAGE 0: POPULATION ///////////////////
|
||||
/////////////////////////////////////////
|
||||
|
||||
var page = pages[0];
|
||||
|
||||
// Labels
|
||||
page.appendChild(_makeLabel("sandbox_population", {x:0, y:0, w:433}));
|
||||
|
||||
// Create an icon, label, and slider... that all interact with each other.
|
||||
var _makePopulationControl = function(x, y, peepID, defaultValue){
|
||||
|
||||
// DOM
|
||||
var popDOM = document.createElement("div");
|
||||
popDOM.className = "sandbox_pop";
|
||||
popDOM.style.left = x;
|
||||
popDOM.style.top = y;
|
||||
page.appendChild(popDOM);
|
||||
|
||||
// Message
|
||||
var message = "sandbox/pop/"+peepID;
|
||||
|
||||
// Icon
|
||||
var popIcon = document.createElement("div");
|
||||
popIcon.className = "sandbox_pop_icon";
|
||||
popIcon.style.backgroundPosition = (-PEEP_METADATA[peepID].frame*40)+"px 0px";
|
||||
popDOM.appendChild(popIcon);
|
||||
|
||||
// Label: Name
|
||||
var popName = document.createElement("div");
|
||||
popName.className = "sandbox_pop_label";
|
||||
popName.innerHTML = Words.get("label_short_"+peepID).toUpperCase();
|
||||
popName.style.color = PEEP_METADATA[peepID].color;
|
||||
popDOM.appendChild(popName);
|
||||
|
||||
// Label: Amount
|
||||
var popAmount = document.createElement("div");
|
||||
popAmount.className = "sandbox_pop_label";
|
||||
popAmount.style.textAlign = "right";
|
||||
popAmount.style.color = PEEP_METADATA[peepID].color;
|
||||
popDOM.appendChild(popAmount);
|
||||
subscribe(message, function(value){
|
||||
popAmount.innerHTML = value;
|
||||
});
|
||||
|
||||
// Slider
|
||||
(function(peepID){
|
||||
var popSlider = new Slider({
|
||||
x:0, y:35, width:200,
|
||||
min:0, max:25, step:1,
|
||||
message: message,
|
||||
onselect: function(){
|
||||
_anchorPopulation(peepID);
|
||||
},
|
||||
onchange: function(value){
|
||||
_adjustPopulation(peepID, value);
|
||||
}
|
||||
});
|
||||
popDOM.appendChild(popSlider.dom);
|
||||
})(peepID);
|
||||
|
||||
// Default value!
|
||||
publish(message, [defaultValue]);
|
||||
|
||||
};
|
||||
var xDiff = 220;
|
||||
var yDiff = 80;
|
||||
var yOff = 40;
|
||||
_makePopulationControl( 0, yOff+0, "tft", 5);
|
||||
_makePopulationControl(xDiff, yOff+0, "all_d", 5);
|
||||
_makePopulationControl( 0, yOff+yDiff, "all_c", 15);
|
||||
_makePopulationControl(xDiff, yOff+yDiff, "grudge", 0);
|
||||
_makePopulationControl( 0, yOff+yDiff*2, "prober", 0);
|
||||
_makePopulationControl(xDiff, yOff+yDiff*2, "tf2t", 0);
|
||||
_makePopulationControl( 0, yOff+yDiff*3, "pavlov", 0);
|
||||
_makePopulationControl(xDiff, yOff+yDiff*3, "random", 0);
|
||||
|
||||
// Adjust the WHOLE population...
|
||||
/******************************
|
||||
|
||||
Adjust by SCALING. (and in the edge case of "all zero", scale equally)
|
||||
Round to integers. (if above or below 25 in total, keep adding/subtracting 1 down the line)
|
||||
|
||||
******************************/
|
||||
var _population;
|
||||
var _remainder;
|
||||
var _anchoredIndex;
|
||||
var _anchorPopulation = function(peepID){
|
||||
|
||||
// Which index should be anchored?
|
||||
_anchoredIndex = Tournament.INITIAL_AGENTS.findIndex(function(config){
|
||||
return config.strategy==peepID;
|
||||
});
|
||||
var initValue = Tournament.INITIAL_AGENTS[_anchoredIndex].count;
|
||||
|
||||
// SPECIAL CASE: THIS IS ALREADY FULL
|
||||
if(initValue==25){
|
||||
|
||||
// Pretend it was 1 for all seven others, 25-7 for this.
|
||||
_population = [];
|
||||
for(var i=0; i<Tournament.INITIAL_AGENTS.length; i++){
|
||||
if(i==_anchoredIndex){
|
||||
_population.push(18);
|
||||
}else{
|
||||
_population.push(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Remainder is 7
|
||||
_remainder = 7;
|
||||
|
||||
}else{
|
||||
|
||||
// Create array of all initial agents...
|
||||
_population = [];
|
||||
for(var i=0; i<Tournament.INITIAL_AGENTS.length; i++){
|
||||
var conf = Tournament.INITIAL_AGENTS[i];
|
||||
_population.push(conf.count);
|
||||
}
|
||||
|
||||
// Remainder sum of those NOT anchored (25-anchor.count)
|
||||
_remainder = 25-initValue;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
var _adjustPopulation = function(peepID, value){
|
||||
|
||||
// Change the anchored one
|
||||
Tournament.INITIAL_AGENTS.find(function(config){
|
||||
return config.strategy==peepID;
|
||||
}).count = value;
|
||||
|
||||
// What's the scale for the rest of 'em?
|
||||
var newRemainder = 25-value;
|
||||
var scale = newRemainder/_remainder;
|
||||
|
||||
// Adjust everyone to scale, ROUNDING.
|
||||
var total = 0;
|
||||
for(var i=0; i<Tournament.INITIAL_AGENTS.length; i++){
|
||||
|
||||
// do NOT adjust anchor.
|
||||
var conf = Tournament.INITIAL_AGENTS[i];
|
||||
if(conf.strategy==peepID) continue;
|
||||
|
||||
var initCount = _population[i];
|
||||
var newCount = Math.round(initCount*scale);
|
||||
conf.count = newCount;
|
||||
|
||||
// Count total!
|
||||
total += newCount;
|
||||
|
||||
}
|
||||
total += value; // total
|
||||
|
||||
// Difference...
|
||||
var diff = 25-total;
|
||||
// If negative, remove one starting from BOTTOM, skipping anchor.
|
||||
if(diff<0){
|
||||
for(var i=Tournament.INITIAL_AGENTS.length-1; i>=0 && diff<0; i--){
|
||||
// do NOT adjust anchor.
|
||||
var conf = Tournament.INITIAL_AGENTS[i];
|
||||
if(conf.strategy==peepID) continue;
|
||||
conf.count--; // REMOVE
|
||||
diff++; // yay
|
||||
}
|
||||
}
|
||||
// If positive, add one starting from top, skipping anchor.
|
||||
if(diff>0){
|
||||
for(var i=0; i<Tournament.INITIAL_AGENTS.length && diff>0; i++){
|
||||
// do NOT adjust anchor.
|
||||
var conf = Tournament.INITIAL_AGENTS[i];
|
||||
if(conf.strategy==peepID) continue;
|
||||
conf.count++; // ADD
|
||||
diff--; // yay
|
||||
}
|
||||
}
|
||||
|
||||
// NOW adjust UI
|
||||
for(var i=0; i<Tournament.INITIAL_AGENTS.length; i++){
|
||||
// do NOT adjust anchor.
|
||||
var conf = Tournament.INITIAL_AGENTS[i];
|
||||
if(conf.strategy==peepID) continue;
|
||||
publish("sandbox/pop/"+conf.strategy, [conf.count]);
|
||||
}
|
||||
|
||||
// Reset!
|
||||
publish("tournament/reset");
|
||||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////
|
||||
// PAGE 1: PAYOFFS //////////////////////
|
||||
/////////////////////////////////////////
|
||||
|
@ -154,10 +341,56 @@ function SandboxUI(config){
|
|||
|
||||
var page = pages[2];
|
||||
|
||||
// Labels
|
||||
page.appendChild(_makeLabel("sandbox_rules_1", {x:0, y:0, w:433}));
|
||||
page.appendChild(_makeLabel("sandbox_rules_2", {x:0, y:100, w:433}));
|
||||
page.appendChild(_makeLabel("sandbox_rules_3", {x:0, y:225, w:433}));
|
||||
// Rule: Number of turns (1 to 50)
|
||||
var rule_turns = _makeLabel("sandbox_rules_1", {x:0, y:0, w:433});
|
||||
var slider_turns = new Slider({
|
||||
x:0, y:35, width:430,
|
||||
min:1, max:50, step:1,
|
||||
message: "rules/turns"
|
||||
});
|
||||
subscribe("rules/turns",function(value){
|
||||
var words = (value==1) ? Words.get("sandbox_rules_1_single") : Words.get("sandbox_rules_1"); // plural?
|
||||
words = words.replace(/\[N\]/g, value+""); // replace [N] with the number value
|
||||
rule_turns.innerHTML = words;
|
||||
});
|
||||
page.appendChild(rule_turns);
|
||||
page.appendChild(slider_turns.dom);
|
||||
|
||||
// Rule: Eliminate/Reproduce how many? (1 to 12)
|
||||
var rule_evolution = _makeLabel("sandbox_rules_2", {x:0, y:100, w:433});
|
||||
var slider_evolution = new Slider({
|
||||
x:0, y:165, width:430,
|
||||
min:1, max:12, step:1,
|
||||
message: "rules/evolution"
|
||||
});
|
||||
subscribe("rules/evolution",function(value){
|
||||
var words = (value==1) ? Words.get("sandbox_rules_2_single") : Words.get("sandbox_rules_2"); // plural?
|
||||
words = words.replace(/\[N\]/g, value+""); // replace [N] with the number value
|
||||
rule_evolution.innerHTML = words;
|
||||
});
|
||||
page.appendChild(rule_evolution);
|
||||
page.appendChild(slider_evolution.dom);
|
||||
|
||||
// Rule: Noise (0% to 50%)
|
||||
var rule_noise = _makeLabel("sandbox_rules_3", {x:0, y:225, w:433});
|
||||
var slider_noise = new Slider({
|
||||
x:0, y:290, width:430,
|
||||
min:0.00, max:0.50, step:0.01,
|
||||
message: "rules/noise"
|
||||
});
|
||||
subscribe("rules/noise",function(value){
|
||||
value = Math.round(value*100);
|
||||
var words = Words.get("sandbox_rules_3");
|
||||
words = words.replace(/\[N\]/g, value+""); // replace [N] with the number value
|
||||
rule_noise.innerHTML = words;
|
||||
});
|
||||
page.appendChild(rule_noise);
|
||||
page.appendChild(slider_noise.dom);
|
||||
|
||||
// DEFAULTS
|
||||
publish("rules/turns", [10]);
|
||||
publish("rules/evolution", [5]);
|
||||
publish("rules/noise", [0.05]);
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Add & Remove Object //////////////////
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
Tournament.SELECTION = 5;
|
||||
subscribe("rules/evolution",function(value){
|
||||
Tournament.SELECTION = value;
|
||||
});
|
||||
|
||||
Tournament.NUM_TURNS = 10;
|
||||
subscribe("rules/turns",function(value){
|
||||
Tournament.NUM_TURNS = value;
|
||||
});
|
||||
|
||||
// CREATE A RING OF AGENTS
|
||||
/*Tournament.AGENTS = [
|
||||
{strategy:"all_c", count:15},
|
||||
{strategy:"all_d", count:5},
|
||||
{strategy:"grudge", count:0},
|
||||
{strategy:"tft", count:5},
|
||||
];*/
|
||||
Tournament.INITIAL_AGENTS = [
|
||||
{strategy:"all_c", count:15},
|
||||
{strategy:"all_d", count:5},
|
||||
{strategy:"tft", count:5},
|
||||
//{strategy:"grudge", count:3},
|
||||
//{strategy:"prober", count:6},
|
||||
//{strategy:"tf2t", count:8},
|
||||
//{strategy:"pavlov", count:3},
|
||||
//{strategy:"random", count:3}
|
||||
{strategy:"all_d", count:5},
|
||||
{strategy:"all_c", count:15},
|
||||
{strategy:"grudge", count:0},
|
||||
{strategy:"prober", count:0},
|
||||
{strategy:"tf2t", count:0},
|
||||
{strategy:"pavlov", count:0},
|
||||
{strategy:"random", count:0}
|
||||
];
|
||||
|
||||
// OH THAT'S SO COOL. Mostly C: Pavlov wins, Mostly D: tit for two tats wins (with 5% mistake!)
|
||||
|
@ -29,15 +30,15 @@ Tournament.INITIAL_AGENTS = [
|
|||
Loader.addToManifest(Loader.manifest,{
|
||||
tournament_peep: "assets/tournament_peep.json"
|
||||
});
|
||||
var PEEP_GRAPHICS = {
|
||||
tft: {frame:0},
|
||||
all_d: {frame:1},
|
||||
all_c: {frame:2},
|
||||
grudge: {frame:3},
|
||||
prober: {frame:4},
|
||||
tf2t: {frame:5},
|
||||
pavlov: {frame:6},
|
||||
random: {frame:7}
|
||||
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"},
|
||||
tf2t: {frame:5, color:"#88A8CE"},
|
||||
pavlov: {frame:6, color:"#86C448"},
|
||||
random: {frame:7, color:"#FF5E5E"}
|
||||
};
|
||||
|
||||
function Tournament(config){
|
||||
|
@ -492,7 +493,7 @@ function TournamentAgent(config){
|
|||
|
||||
// Body!
|
||||
var body = _makeMovieClip("tournament_peep");
|
||||
body.gotoAndStop(PEEP_GRAPHICS[config.strategy].frame);
|
||||
body.gotoAndStop(PEEP_METADATA[config.strategy].frame);
|
||||
body.scale.set(0.5);
|
||||
body.anchor.x = 0.5;
|
||||
body.anchor.y = 0.75;
|
||||
|
@ -513,10 +514,7 @@ function TournamentAgent(config){
|
|||
};
|
||||
self.updateScore();
|
||||
scoreText.visible = false;
|
||||
/*subscribe("tournament/play",function(){
|
||||
scoreText.visible = false;
|
||||
});*/
|
||||
subscribe("tournament/reproduce",function(){
|
||||
var _handle = subscribe("tournament/reproduce",function(){
|
||||
scoreText.visible = false;
|
||||
});
|
||||
|
||||
|
@ -581,6 +579,9 @@ function TournamentAgent(config){
|
|||
// AND remove self from tournament
|
||||
self.tournament.actuallyRemoveAgent(self);
|
||||
|
||||
// Unsub
|
||||
unsubscribe(_handle);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
26
lang/en.html
26
lang/en.html
|
@ -3,7 +3,7 @@
|
|||
<!-- - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<p id="sandbox_population">
|
||||
Start the simulation with this distribution of players:
|
||||
Start off with this distribution of players:
|
||||
</p>
|
||||
|
||||
<p id="sandbox_payoffs">
|
||||
|
@ -45,6 +45,9 @@ In each round of a one-on-one game, there's a [N]% chance a player makes a mista
|
|||
<p id="label_tft">
|
||||
Tit For Tat
|
||||
</p>
|
||||
<p id="label_short_tft">
|
||||
copycat
|
||||
</p>
|
||||
<p id="desc_tft">
|
||||
I Cooperate on the first round.
|
||||
Then, I just do whatever you did the last round.
|
||||
|
@ -55,6 +58,9 @@ but if you Cooperate, I'll forgive you immediately!
|
|||
<p id="label_all_d">
|
||||
Always Cheat
|
||||
</p>
|
||||
<p id="label_short_all_d">
|
||||
sinner
|
||||
</p>
|
||||
<p id="desc_all_d">
|
||||
Ain't I a stinker?
|
||||
</p>
|
||||
|
@ -62,6 +68,9 @@ Ain't I a stinker?
|
|||
<p id="label_all_c">
|
||||
Always Cooperate
|
||||
</p>
|
||||
<p id="label_short_all_c">
|
||||
saint
|
||||
</p>
|
||||
<p id="desc_all_c">
|
||||
💖 💖 💖
|
||||
</p>
|
||||
|
@ -69,6 +78,9 @@ Always Cooperate
|
|||
<p id="label_grudge">
|
||||
Grudger
|
||||
</p>
|
||||
<p id="label_short_grudge">
|
||||
grudger
|
||||
</p>
|
||||
<p id="desc_grudge">
|
||||
I'll always Cooperate... until you Cheat me even once.
|
||||
Then, I'll <i>always</i> Cheat you back. NO FORGIVENESS.
|
||||
|
@ -77,6 +89,9 @@ Then, I'll <i>always</i> Cheat you back. NO FORGIVENESS.
|
|||
<p id="label_prober">
|
||||
Prober
|
||||
</p>
|
||||
<p id="label_short_prober">
|
||||
detective
|
||||
</p>
|
||||
<p id="desc_prober">
|
||||
First: I analyze you.
|
||||
I start: Cooperate, Cheat, Cooperate, Cooperate.
|
||||
|
@ -88,6 +103,9 @@ My dear Watson: elementary.
|
|||
<p id="label_tf2t">
|
||||
Tit For Two Tats
|
||||
</p>
|
||||
<p id="label_short_tf2t">
|
||||
copykitten
|
||||
</p>
|
||||
<p id="desc_tf2t">
|
||||
I Cooperate on the first round.
|
||||
After that, if you Cheat me... well, I'll forgive you once.
|
||||
|
@ -98,6 +116,9 @@ However, if you Cheat me twice in a row, <i>then</i> I'll Cheat back.
|
|||
<p id="label_pavlov">
|
||||
Pavlov's Dog
|
||||
</p>
|
||||
<p id="label_short_pavlov">
|
||||
pavlov
|
||||
</p>
|
||||
<p id="desc_pavlov">
|
||||
I Cooperate on the first round.
|
||||
After that, if you Cooperated in the previous round,
|
||||
|
@ -109,6 +130,9 @@ I'll do the <i>opposite</i> of what I did last time (even if it was a mistake).
|
|||
<p id="label_random">
|
||||
Lol So Random
|
||||
</p>
|
||||
<p id="label_short_random">
|
||||
random
|
||||
</p>
|
||||
<p id="desc_random">
|
||||
monkey tacos! robot ninja bacon pirate!
|
||||
i randomly play Cheat or Cooperate coz lol i'm so random
|
||||
|
|
Loading…
Reference in a new issue