2017-07-12 21:46:38 +00:00
|
|
|
Tournament.resetGlobalVariables = function(){
|
|
|
|
|
|
|
|
Tournament.SELECTION = 5;
|
|
|
|
Tournament.NUM_TURNS = 10;
|
|
|
|
|
|
|
|
Tournament.INITIAL_AGENTS = [
|
2017-07-20 22:16:35 +00:00
|
|
|
{strategy:"tft", count:3},
|
|
|
|
{strategy:"all_d", count:3},
|
|
|
|
{strategy:"all_c", count:3},
|
|
|
|
{strategy:"grudge", count:3},
|
|
|
|
{strategy:"prober", count:3},
|
|
|
|
{strategy:"tf2t", count:3},
|
|
|
|
{strategy:"pavlov", count:3},
|
|
|
|
{strategy:"random", count:4}
|
2017-07-12 21:46:38 +00:00
|
|
|
];
|
|
|
|
|
2017-07-17 19:39:26 +00:00
|
|
|
Tournament.FLOWER_CONNECTIONS = false;
|
|
|
|
|
2017-07-12 21:46:38 +00:00
|
|
|
publish("pd/defaultPayoffs");
|
|
|
|
|
|
|
|
PD.NOISE = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
Tournament.resetGlobalVariables();
|
|
|
|
|
2017-06-29 02:12:32 +00:00
|
|
|
subscribe("rules/evolution",function(value){
|
|
|
|
Tournament.SELECTION = value;
|
|
|
|
});
|
|
|
|
|
|
|
|
subscribe("rules/turns",function(value){
|
|
|
|
Tournament.NUM_TURNS = value;
|
|
|
|
});
|
2017-06-23 21:57:22 +00:00
|
|
|
|
2017-06-28 14:53:43 +00:00
|
|
|
// OH THAT'S SO COOL. Mostly C: Pavlov wins, Mostly D: tit for two tats wins (with 5% mistake!)
|
|
|
|
// ALSO, NOISE: tft vs all_d. no random: tft wins. low random: tf2t wins. high random: all_d wins. totally random: nobody wins
|
|
|
|
|
2017-06-27 17:49:58 +00:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
|
|
|
|
// REGULAR LOAD
|
|
|
|
Loader.addToManifest(Loader.manifest,{
|
2017-07-17 19:39:26 +00:00
|
|
|
tournament_peep: "assets/tournament/tournament_peep.json",
|
|
|
|
connection_flower: "assets/tournament/connection_flower.json"
|
2017-06-27 17:49:58 +00:00
|
|
|
});
|
|
|
|
|
2017-06-23 21:57:22 +00:00
|
|
|
function Tournament(config){
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
var self = this;
|
|
|
|
self.id = config.id;
|
|
|
|
|
|
|
|
// APP
|
2017-06-21 14:51:55 +00:00
|
|
|
var app = new PIXI.Application(500, 500, {transparent:true, resolution:2});
|
2017-06-20 11:10:41 +00:00
|
|
|
self.dom = app.view;
|
|
|
|
|
|
|
|
// DOM
|
|
|
|
self.dom.className = "object";
|
2017-06-21 14:51:55 +00:00
|
|
|
self.dom.style.width = 500;
|
|
|
|
self.dom.style.height = 500;
|
2017-06-20 11:10:41 +00:00
|
|
|
self.dom.style.left = config.x+"px";
|
|
|
|
self.dom.style.top = config.y+"px";
|
2017-06-21 20:05:44 +00:00
|
|
|
//self.dom.style.border = "1px solid rgba(0,0,0,0.2)";
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
var _convertCountToArray = function(countList){
|
|
|
|
var array = [];
|
2017-06-28 14:53:43 +00:00
|
|
|
for(var i=0; i<AGENTS.length; i++){
|
|
|
|
var A = AGENTS[i];
|
2017-06-20 11:10:41 +00:00
|
|
|
var strategy = A.strategy;
|
|
|
|
var count = A.count;
|
|
|
|
for(var j=0; j<count; j++){
|
|
|
|
array.push(strategy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
};
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
self.agents = [];
|
|
|
|
self.connections = [];
|
|
|
|
|
2017-06-21 14:51:55 +00:00
|
|
|
self.networkContainer = new PIXI.Container();
|
|
|
|
self.agentsContainer = new PIXI.Container();
|
|
|
|
app.stage.addChild(self.networkContainer);
|
|
|
|
app.stage.addChild(self.agentsContainer);
|
|
|
|
|
2017-06-20 11:10:41 +00:00
|
|
|
self.populateAgents = function(){
|
|
|
|
|
|
|
|
// Clear EVERYTHING
|
2017-06-28 20:28:15 +00:00
|
|
|
while(self.agents.length>0) self.agents[0].kill();
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// Convert to an array
|
2017-06-28 14:53:43 +00:00
|
|
|
self.agents = _convertCountToArray(AGENTS);
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// Put 'em in a ring
|
|
|
|
var count = 0;
|
|
|
|
for(var i=0; i<self.agents.length; i++){
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// Angle
|
2017-06-20 11:10:41 +00:00
|
|
|
var angle = (i/self.agents.length)*Math.TAU - Math.TAU/4;
|
|
|
|
|
|
|
|
// What kind of agent?
|
|
|
|
var strategy = self.agents[i];
|
2017-06-21 20:05:44 +00:00
|
|
|
var agent = new TournamentAgent({angle:angle, strategy:strategy, tournament:self});
|
|
|
|
self.agentsContainer.addChild(agent.graphics);
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// Remember me!
|
|
|
|
self.agents[i] = agent;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// (sort agents by depth)
|
|
|
|
self.sortAgentsByDepth();
|
|
|
|
|
|
|
|
};
|
|
|
|
self.sortAgentsByDepth = function(){
|
|
|
|
self.agentsContainer.children.sort(function(a,b){
|
|
|
|
return a.y - b.y;
|
|
|
|
});
|
2017-06-20 11:10:41 +00:00
|
|
|
};
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
self.createNetwork = function(){
|
|
|
|
|
|
|
|
// Clear EVERYTHING
|
2017-06-28 20:28:15 +00:00
|
|
|
while(self.connections.length>0) self.connections[0].kill();
|
2017-06-21 20:05:44 +00:00
|
|
|
|
|
|
|
// Connect all of 'em
|
|
|
|
for(var i=0; i<self.agents.length; i++){
|
|
|
|
var playerA = self.agents[i];
|
2017-07-17 19:39:26 +00:00
|
|
|
var flip = false;
|
2017-06-21 20:05:44 +00:00
|
|
|
for(var j=i+1; j<self.agents.length; j++){
|
|
|
|
var playerB = self.agents[j];
|
|
|
|
var connection = new TournamentConnection({
|
2017-06-28 20:28:15 +00:00
|
|
|
tournament: self,
|
|
|
|
from: playerA,
|
2017-07-17 19:39:26 +00:00
|
|
|
to: playerB,
|
|
|
|
flower_flip: flip
|
2017-06-21 20:05:44 +00:00
|
|
|
});
|
|
|
|
self.networkContainer.addChild(connection.graphics);
|
|
|
|
self.connections.push(connection);
|
2017-07-17 19:39:26 +00:00
|
|
|
flip = !flip;
|
2017-06-21 20:05:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
2017-06-28 20:28:15 +00:00
|
|
|
self.actuallyRemoveConnection = function(connection){
|
|
|
|
var index = self.connections.indexOf(connection);
|
|
|
|
self.connections.splice(index,1);
|
|
|
|
};
|
2017-06-28 14:53:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
///////////////////////
|
|
|
|
// RESET //////////////
|
|
|
|
///////////////////////
|
|
|
|
|
|
|
|
var AGENTS;
|
|
|
|
self.reset = function(){
|
2017-06-28 20:28:15 +00:00
|
|
|
|
|
|
|
// Agents & Network...
|
2017-06-28 14:53:43 +00:00
|
|
|
AGENTS = JSON.parse(JSON.stringify(Tournament.INITIAL_AGENTS));
|
|
|
|
self.populateAgents();
|
|
|
|
self.createNetwork();
|
2017-06-28 20:28:15 +00:00
|
|
|
|
|
|
|
// Animation...
|
|
|
|
self.STAGE = STAGE_REST;
|
|
|
|
_playIndex = 0;
|
|
|
|
_tweenTimer = 0;
|
|
|
|
|
|
|
|
// Stop autoplay!
|
|
|
|
publish("tournament/autoplay/stop");
|
|
|
|
_step = 0;
|
|
|
|
|
2017-06-28 14:53:43 +00:00
|
|
|
};
|
|
|
|
|
2017-07-13 15:07:33 +00:00
|
|
|
listen(self, "tournament/reset", self.reset);
|
2017-06-28 14:53:43 +00:00
|
|
|
|
|
|
|
self.reset();
|
2017-06-21 20:05:44 +00:00
|
|
|
|
2017-07-17 19:39:26 +00:00
|
|
|
////////////////////////////////////
|
|
|
|
// 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();
|
|
|
|
};
|
|
|
|
|
2017-06-20 11:10:41 +00:00
|
|
|
////////////////////////////////////
|
|
|
|
// EVOLUTION ///////////////////////
|
|
|
|
////////////////////////////////////
|
|
|
|
|
|
|
|
// Play one tournament
|
2017-06-21 20:05:44 +00:00
|
|
|
self.agentsSorted = null;
|
2017-06-20 11:10:41 +00:00
|
|
|
self.playOneTournament = function(){
|
2017-06-23 21:57:22 +00:00
|
|
|
PD.playOneTournament(self.agents, Tournament.NUM_TURNS);
|
2017-06-21 20:05:44 +00:00
|
|
|
self.agentsSorted = self.agents.slice();
|
|
|
|
self.agentsSorted.sort(function(a,b){
|
2017-06-20 11:10:41 +00:00
|
|
|
if(a.coins==b.coins) return (Math.random()<0.5); // if equal, random
|
|
|
|
return a.coins-b.coins; // otherwise, sort as per usual
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// Get rid of X worst
|
|
|
|
self.eliminateBottom = function(X){
|
|
|
|
|
|
|
|
// The worst X
|
2017-06-21 20:05:44 +00:00
|
|
|
var worst = self.agentsSorted.slice(0,X);
|
2017-06-20 11:10:41 +00:00
|
|
|
|
2017-06-28 14:53:43 +00:00
|
|
|
// For each one, subtract from AGENTS count, and KILL.
|
2017-06-20 11:10:41 +00:00
|
|
|
for(var i=0; i<worst.length; i++){
|
|
|
|
var badAgent = worst[i];
|
2017-06-28 14:53:43 +00:00
|
|
|
var config = AGENTS.find(function(config){
|
2017-06-20 11:10:41 +00:00
|
|
|
return config.strategy==badAgent.strategyName;
|
|
|
|
});
|
|
|
|
config.count--; // remove one
|
2017-06-28 20:28:15 +00:00
|
|
|
badAgent.eliminate(); // ELIMINATE
|
2017-06-20 11:10:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
};
|
2017-06-21 20:05:44 +00:00
|
|
|
self.actuallyRemoveAgent = function(agent){
|
|
|
|
var index = self.agents.indexOf(agent);
|
|
|
|
self.agents.splice(index,1);
|
|
|
|
};
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// Reproduce the top X
|
|
|
|
self.reproduceTop = function(X){
|
|
|
|
|
|
|
|
// The top X
|
2017-06-21 20:05:44 +00:00
|
|
|
var best = self.agentsSorted.slice(self.agentsSorted.length-X, self.agentsSorted.length);
|
2017-06-20 11:10:41 +00:00
|
|
|
|
2017-06-28 14:53:43 +00:00
|
|
|
// For each one, add to AGENTS count
|
2017-06-20 11:10:41 +00:00
|
|
|
for(var i=0; i<best.length; i++){
|
|
|
|
var goodAgent = best[i];
|
2017-06-28 14:53:43 +00:00
|
|
|
var config = AGENTS.find(function(config){
|
2017-06-20 11:10:41 +00:00
|
|
|
return config.strategy==goodAgent.strategyName;
|
|
|
|
});
|
|
|
|
config.count++; // ADD one
|
|
|
|
}
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// ADD agents, splicing right AFTER
|
|
|
|
for(var i=0; i<best.length; i++){
|
|
|
|
|
|
|
|
// Properties...
|
|
|
|
var goodAgent = best[i];
|
|
|
|
var angle = goodAgent.angle + 0.1;
|
|
|
|
var strategy = goodAgent.strategyName;
|
|
|
|
|
|
|
|
// Create agent!
|
|
|
|
var agent = new TournamentAgent({angle:angle, strategy:strategy, tournament:self});
|
|
|
|
self.agentsContainer.addChild(agent.graphics);
|
|
|
|
|
|
|
|
// Splice RIGHT AFTER
|
|
|
|
var index = self.agents.indexOf(goodAgent);
|
|
|
|
self.agents.splice(index, 0, agent);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// What are the agents' GO-TO angles?
|
|
|
|
for(var i=0; i<self.agents.length; i++){
|
|
|
|
var agent = self.agents[i];
|
|
|
|
var angle = (i/self.agents.length)*Math.TAU - Math.TAU/4;
|
|
|
|
agent.gotoAngle = angle;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ADD connections
|
|
|
|
self.createNetwork();
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// ANIMATE the PLAYING, ELIMINATING, or REPRODUCING
|
|
|
|
var STAGE_REST = 0;
|
|
|
|
var STAGE_PLAY = 1;
|
|
|
|
var STAGE_ELIMINATE = 2;
|
|
|
|
var STAGE_REPRODUCE = 3;
|
|
|
|
self.STAGE = STAGE_REST;
|
|
|
|
|
2017-06-28 14:53:43 +00:00
|
|
|
// AUTOPLAY
|
|
|
|
self.isAutoPlaying = false;
|
|
|
|
var _step = 0;
|
|
|
|
var _nextStep = function(){
|
2017-06-28 20:28:15 +00:00
|
|
|
if(self.STAGE!=STAGE_REST) return;
|
2017-06-28 14:53:43 +00:00
|
|
|
if(_step==0) publish("tournament/play");
|
|
|
|
if(_step==1) publish("tournament/eliminate");
|
|
|
|
if(_step==2) publish("tournament/reproduce");
|
|
|
|
_step = (_step+1)%3;
|
2017-06-20 11:10:41 +00:00
|
|
|
};
|
2017-06-28 14:53:43 +00:00
|
|
|
var _startAutoPlay = function(){
|
|
|
|
self.isAutoPlaying = true;
|
|
|
|
_nextStep();
|
|
|
|
setTimeout(function(){
|
|
|
|
if(self.isAutoPlaying) _startAutoPlay();
|
2017-07-19 22:49:53 +00:00
|
|
|
},150);
|
2017-06-28 14:53:43 +00:00
|
|
|
};
|
2017-06-28 20:28:15 +00:00
|
|
|
var _stopAutoPlay = function(){
|
2017-06-28 14:53:43 +00:00
|
|
|
self.isAutoPlaying = false;
|
2017-06-28 20:28:15 +00:00
|
|
|
};
|
2017-07-13 15:07:33 +00:00
|
|
|
listen(self, "tournament/autoplay/start", _startAutoPlay);
|
|
|
|
listen(self, "tournament/autoplay/stop", _stopAutoPlay);
|
|
|
|
listen(self, "tournament/step", function(){
|
2017-06-28 20:28:15 +00:00
|
|
|
publish("tournament/autoplay/stop");
|
2017-06-28 14:53:43 +00:00
|
|
|
_nextStep();
|
|
|
|
});
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// ANIMATE
|
2017-06-21 20:05:44 +00:00
|
|
|
var _playIndex = 0;
|
|
|
|
var _tweenTimer = 0;
|
2017-07-20 22:16:35 +00:00
|
|
|
var _tick = function(delta){
|
2017-06-21 20:05:44 +00:00
|
|
|
|
2017-06-28 20:28:15 +00:00
|
|
|
// Tick
|
|
|
|
Tween.tick();
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// PLAY!
|
|
|
|
if(self.STAGE == STAGE_PLAY){
|
2017-07-19 22:49:53 +00:00
|
|
|
/*if(self.isAutoPlaying){
|
2017-06-21 20:05:44 +00:00
|
|
|
self.playOneTournament(); // FOR REAL, NOW.
|
|
|
|
_playIndex = 0;
|
2017-06-28 20:28:15 +00:00
|
|
|
_tweenTimer = 0;
|
2017-06-21 20:05:44 +00:00
|
|
|
self.STAGE = STAGE_REST;
|
2017-07-17 19:39:26 +00:00
|
|
|
publish("tournament/step/completed", ["play"]);
|
2017-07-19 22:49:53 +00:00
|
|
|
}else{*/
|
|
|
|
if(_playIndex>0 && _playIndex<self.agents.length+1) self.agents[_playIndex-1].dehighlightConnections();
|
|
|
|
if(_playIndex>1 && _playIndex<self.agents.length+2) self.agents[_playIndex-2].dehighlightConnections();
|
|
|
|
if(_playIndex<self.agents.length){
|
|
|
|
self.agents[_playIndex].highlightConnections();
|
|
|
|
_playIndex += self.isAutoPlaying ? 2 : 1;
|
|
|
|
}else{
|
|
|
|
self.playOneTournament(); // FOR REAL, NOW.
|
|
|
|
_playIndex = 0;
|
|
|
|
_tweenTimer = 0;
|
|
|
|
self.STAGE = STAGE_REST;
|
|
|
|
publish("tournament/step/completed", ["play"]);
|
|
|
|
}
|
|
|
|
//}
|
2017-06-21 20:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ELIMINATE!
|
|
|
|
if(self.STAGE == STAGE_ELIMINATE){
|
2017-06-23 21:57:22 +00:00
|
|
|
self.eliminateBottom(Tournament.SELECTION);
|
2017-06-28 20:28:15 +00:00
|
|
|
_tweenTimer++;
|
2017-07-19 22:49:53 +00:00
|
|
|
if(_tweenTimer==_s(0.3) || self.isAutoPlaying){
|
2017-06-28 20:28:15 +00:00
|
|
|
_tweenTimer = 0;
|
|
|
|
self.STAGE = STAGE_REST;
|
2017-07-17 19:39:26 +00:00
|
|
|
publish("tournament/step/completed", ["eliminate"]);
|
2017-06-28 20:28:15 +00:00
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// REPRODUCE!
|
|
|
|
if(self.STAGE == STAGE_REPRODUCE){
|
|
|
|
|
|
|
|
// Start
|
|
|
|
if(_tweenTimer==0){
|
2017-06-23 21:57:22 +00:00
|
|
|
self.reproduceTop(Tournament.SELECTION);
|
2017-06-21 20:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Middle...
|
2017-07-19 22:49:53 +00:00
|
|
|
_tweenTimer += self.isAutoPlaying ? 0.15 : 0.05;
|
2017-07-20 22:16:35 +00:00
|
|
|
if(_tweenTimer>1) _tweenTimer=1;
|
2017-06-21 20:05:44 +00:00
|
|
|
for(var i=0;i<self.agents.length;i++){
|
|
|
|
var a = self.agents[i];
|
|
|
|
a.tweenAngle(_tweenTimer);
|
|
|
|
a.updatePosition();
|
|
|
|
}
|
|
|
|
self.sortAgentsByDepth();
|
|
|
|
for(var i=0;i<self.connections.length;i++) self.connections[i].updateGraphics();
|
|
|
|
|
|
|
|
// End
|
|
|
|
if(_tweenTimer>=1){
|
|
|
|
_tweenTimer = 0;
|
|
|
|
self.STAGE = STAGE_REST;
|
2017-07-17 19:39:26 +00:00
|
|
|
publish("tournament/step/completed", ["reproduce"]);
|
2017-06-21 20:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-07-20 22:16:35 +00:00
|
|
|
};
|
|
|
|
app.ticker.add(_tick);
|
2017-06-21 20:05:44 +00:00
|
|
|
|
|
|
|
// PLAY A TOURNAMENT
|
2017-06-21 21:53:53 +00:00
|
|
|
self._startPlay = function(){
|
|
|
|
self.STAGE=STAGE_PLAY;
|
|
|
|
};
|
2017-07-13 15:07:33 +00:00
|
|
|
listen(self, "tournament/play", self._startPlay);
|
2017-06-21 21:53:53 +00:00
|
|
|
self._startEliminate = function(){
|
|
|
|
self.STAGE=STAGE_ELIMINATE;
|
|
|
|
};
|
2017-07-13 15:07:33 +00:00
|
|
|
listen(self, "tournament/eliminate", self._startEliminate);
|
2017-06-21 21:53:53 +00:00
|
|
|
self._startReproduce = function(){
|
|
|
|
self.STAGE=STAGE_REPRODUCE;
|
|
|
|
};
|
2017-07-13 15:07:33 +00:00
|
|
|
listen(self, "tournament/reproduce", self._startReproduce);
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// Add...
|
2017-07-13 18:49:49 +00:00
|
|
|
self.add = function(){
|
|
|
|
_add(self);
|
2017-06-20 11:10:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Remove...
|
2017-07-13 18:49:49 +00:00
|
|
|
self.remove = function(){
|
2017-07-13 15:41:43 +00:00
|
|
|
_stopAutoPlay();
|
2017-07-13 15:07:33 +00:00
|
|
|
for(var i=0; i<self.agents.length; i++) unlisten(self.agents[i]);
|
|
|
|
unlisten(self);
|
2017-07-12 13:42:17 +00:00
|
|
|
app.destroy();
|
2017-07-13 18:49:49 +00:00
|
|
|
_remove(self);
|
2017-06-20 11:10:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
function TournamentConnection(config){
|
|
|
|
|
|
|
|
var self = this;
|
2017-06-28 20:28:15 +00:00
|
|
|
self.config = config;
|
|
|
|
self.tournament = config.tournament;
|
2017-06-21 20:05:44 +00:00
|
|
|
|
|
|
|
// Connect from & to
|
|
|
|
self.from = config.from;
|
|
|
|
self.to = config.to;
|
|
|
|
self.from.connections.push(self);
|
|
|
|
self.to.connections.push(self);
|
|
|
|
|
|
|
|
// Graphics!
|
2017-07-17 19:39:26 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
self.graphics = g;
|
2017-07-17 19:39:26 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
|
|
|
|
// Highlight or no?
|
|
|
|
self.highlight = function(){
|
2017-07-17 19:39:26 +00:00
|
|
|
if(Tournament.FLOWER_CONNECTIONS){
|
|
|
|
_updateFlower(true);
|
|
|
|
}else{
|
|
|
|
g.height = 3;
|
|
|
|
g.gotoAndStop(1);
|
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
};
|
|
|
|
self.dehighlight = function(){
|
2017-07-17 19:39:26 +00:00
|
|
|
if(Tournament.FLOWER_CONNECTIONS){
|
|
|
|
_updateFlower(false);
|
|
|
|
}else{
|
|
|
|
g.height = 1;
|
|
|
|
g.gotoAndStop(0);
|
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
};
|
|
|
|
self.dehighlight();
|
|
|
|
|
|
|
|
// Stretch dat bad boy
|
|
|
|
self.updateGraphics = function(){
|
|
|
|
|
|
|
|
var f = self.from.graphics;
|
|
|
|
var t = self.to.graphics;
|
|
|
|
var dx = t.x-f.x;
|
|
|
|
var dy = t.y-f.y;
|
|
|
|
var a = Math.atan2(dy,dx);
|
|
|
|
var dist = Math.sqrt(dx*dx+dy*dy);
|
|
|
|
|
|
|
|
g.x = f.x;
|
|
|
|
g.y = f.y;
|
|
|
|
|
2017-07-17 19:39:26 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
self.updateGraphics();
|
|
|
|
|
|
|
|
// KILL
|
|
|
|
self.IS_DEAD = false;
|
|
|
|
self.kill = function(){
|
|
|
|
if(self.IS_DEAD) return;
|
|
|
|
self.IS_DEAD = true;
|
2017-06-28 20:28:15 +00:00
|
|
|
self.graphics.parent.removeChild(self.graphics); // remove self's graphics
|
|
|
|
self.tournament.actuallyRemoveConnection(self);
|
2017-06-21 20:05:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
2017-06-20 11:10:41 +00:00
|
|
|
function TournamentAgent(config){
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
self.strategyName = config.strategy;
|
2017-06-21 20:05:44 +00:00
|
|
|
self.tournament = config.tournament;
|
|
|
|
self.angle = config.angle;
|
|
|
|
self.gotoAngle = self.angle;
|
|
|
|
|
|
|
|
// Connections
|
|
|
|
self.connections = [];
|
|
|
|
self.highlightConnections = function(){
|
|
|
|
for(var i=0;i<self.connections.length;i++) self.connections[i].highlight();
|
|
|
|
};
|
|
|
|
self.dehighlightConnections = function(){
|
|
|
|
for(var i=0;i<self.connections.length;i++) self.connections[i].dehighlight();
|
|
|
|
};
|
|
|
|
self.clearConnections = function(){
|
2017-06-28 20:28:15 +00:00
|
|
|
for(var i=0;i<self.connections.length;i++){
|
|
|
|
self.connections[i].kill();
|
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
self.connections = [];
|
|
|
|
};
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// Number of coins
|
|
|
|
self.coins = 0;
|
|
|
|
self.addPayoff = function(payoff){
|
|
|
|
self.coins += payoff;
|
|
|
|
self.updateScore();
|
|
|
|
};
|
|
|
|
|
|
|
|
// What's the image?
|
|
|
|
var g = new PIXI.Container();
|
|
|
|
self.graphics = g;
|
|
|
|
|
|
|
|
// Body!
|
2017-06-27 17:49:58 +00:00
|
|
|
var body = _makeMovieClip("tournament_peep");
|
2017-06-29 02:12:32 +00:00
|
|
|
body.gotoAndStop(PEEP_METADATA[config.strategy].frame);
|
2017-06-21 14:51:55 +00:00
|
|
|
body.scale.set(0.5);
|
2017-06-21 20:05:44 +00:00
|
|
|
body.anchor.x = 0.5;
|
|
|
|
body.anchor.y = 0.75;
|
2017-06-20 11:10:41 +00:00
|
|
|
g.addChild(body);
|
|
|
|
|
|
|
|
// Score!
|
|
|
|
var textStyle = new PIXI.TextStyle({
|
2017-06-21 20:05:44 +00:00
|
|
|
fontFamily: "FuturaHandwritten",
|
2017-06-20 11:10:41 +00:00
|
|
|
fontSize: 16,
|
2017-06-21 20:05:44 +00:00
|
|
|
fill: "#444"
|
2017-06-20 11:10:41 +00:00
|
|
|
});
|
|
|
|
var scoreText = new PIXI.Text("", textStyle);
|
|
|
|
scoreText.anchor.x = 0.5;
|
|
|
|
g.addChild(scoreText);
|
|
|
|
self.updateScore = function(){
|
2017-06-21 20:05:44 +00:00
|
|
|
scoreText.visible = true;
|
2017-06-20 11:10:41 +00:00
|
|
|
scoreText.text = self.coins;
|
|
|
|
};
|
|
|
|
self.updateScore();
|
2017-06-21 20:05:44 +00:00
|
|
|
scoreText.visible = false;
|
2017-07-13 15:07:33 +00:00
|
|
|
listen(self, "tournament/reproduce",function(){
|
2017-06-21 20:05:44 +00:00
|
|
|
scoreText.visible = false;
|
|
|
|
});
|
2017-06-20 11:10:41 +00:00
|
|
|
|
|
|
|
// What's the play logic?
|
|
|
|
var LogicClass = window["Logic_"+self.strategyName];
|
|
|
|
self.logic = new LogicClass();
|
|
|
|
self.play = function(){
|
|
|
|
return self.logic.play();
|
|
|
|
};
|
2017-06-23 21:57:22 +00:00
|
|
|
self.remember = function(own, other){
|
|
|
|
self.logic.remember(own, other);
|
2017-06-20 11:10:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Reset!
|
|
|
|
self.resetCoins = function(){
|
|
|
|
self.coins = 0; // reset coins;
|
|
|
|
self.updateScore();
|
|
|
|
}
|
|
|
|
self.resetLogic = function(){
|
|
|
|
self.logic = new LogicClass(); // reset logic
|
|
|
|
};
|
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// Tween angle...
|
|
|
|
self.tweenAngle = function(t){
|
|
|
|
self.angle = self.gotoAngle*t + self.angle*(1-t);
|
|
|
|
};
|
|
|
|
self.updatePosition = function(){
|
|
|
|
g.x = Math.cos(self.angle)*200 + 250;
|
2017-06-21 21:53:53 +00:00
|
|
|
g.y = Math.sin(self.angle)*200 + 265;
|
2017-06-21 20:05:44 +00:00
|
|
|
scoreText.x = -Math.cos(self.angle)*40;
|
|
|
|
scoreText.y = -Math.sin(self.angle)*48 - 22;
|
2017-06-21 21:53:53 +00:00
|
|
|
body.scale.x = Math.abs(body.scale.x) * ((Math.cos(self.angle)<0) ? 1 : -1);
|
2017-06-21 20:05:44 +00:00
|
|
|
};
|
|
|
|
self.updatePosition();
|
2017-06-20 11:10:41 +00:00
|
|
|
|
2017-06-28 20:28:15 +00:00
|
|
|
// ELIMINATE
|
|
|
|
self.eliminate = function(){
|
|
|
|
|
|
|
|
// INSTA-KILL ALL CONNECTIONS
|
|
|
|
self.clearConnections();
|
2017-07-19 22:49:53 +00:00
|
|
|
scoreText.visible = false;
|
2017-06-20 11:10:41 +00:00
|
|
|
|
2017-06-21 20:05:44 +00:00
|
|
|
// Tween -- DIE!
|
2017-07-19 22:49:53 +00:00
|
|
|
var duration = self.tournament.isAutoPlaying ? 0.13 : 0.3;
|
2017-06-28 20:28:15 +00:00
|
|
|
Tween_get(g).to({
|
2017-06-21 20:05:44 +00:00
|
|
|
alpha: 0,
|
|
|
|
x: g.x+Math.random()*20-10,
|
|
|
|
y: g.y+Math.random()*20-10,
|
|
|
|
rotation: Math.random()*0.5-0.25
|
2017-07-19 22:49:53 +00:00
|
|
|
}, _s(duration), Ease.circOut).call(self.kill);
|
2017-06-21 20:05:44 +00:00
|
|
|
|
2017-06-28 20:28:15 +00:00
|
|
|
};
|
2017-06-20 11:10:41 +00:00
|
|
|
|
2017-06-28 20:28:15 +00:00
|
|
|
// KILL (actually insta-remove)
|
|
|
|
self.kill = function(){
|
|
|
|
|
|
|
|
// Remove ANY tweens
|
|
|
|
Tween.removeTweens(g);
|
|
|
|
|
|
|
|
// NOW remove graphics.
|
|
|
|
g.parent.removeChild(g);
|
|
|
|
|
|
|
|
// AND remove self from tournament
|
|
|
|
self.tournament.actuallyRemoveAgent(self);
|
2017-06-20 11:10:41 +00:00
|
|
|
|
2017-06-29 02:12:32 +00:00
|
|
|
// Unsub
|
2017-07-13 15:07:33 +00:00
|
|
|
unlisten(self);
|
2017-06-29 02:12:32 +00:00
|
|
|
|
2017-06-20 11:10:41 +00:00
|
|
|
};
|
2017-06-21 20:05:44 +00:00
|
|
|
|
2017-06-20 11:10:41 +00:00
|
|
|
}
|
2017-06-21 20:05:44 +00:00
|
|
|
|