180 lines
No EOL
5.4 KiB
JavaScript
180 lines
No EOL
5.4 KiB
JavaScript
const ALLC = function allwaysCooperate(foeHistory) {
|
|
return true;
|
|
}
|
|
|
|
const ALLD = function allwaysDefect(foeHistory) {
|
|
return false;
|
|
}
|
|
|
|
const RAND = function randomChoice(foeHistory) {
|
|
if (Math.random() > 0.5) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const TFT = function titForThat(foeHistory) {
|
|
if (foeHistory.length === 0) {
|
|
return true;
|
|
}
|
|
return foeHistory[foeHistory.length - 1];
|
|
}
|
|
|
|
const STFT = function suspiciousTitForTat(foeHistory) {
|
|
if (foeHistory.length === 0) {
|
|
return false;
|
|
}
|
|
return foeHistory[foeHistory.length - 1];
|
|
}
|
|
|
|
const GRIM = function grimTrigger(foeHistory) {
|
|
if (foeHistory.some(e => e === false)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const MAJ = function majority(foeHistory) {
|
|
let nbTrue = 0;
|
|
let nbFalse = 0;
|
|
|
|
for (const valeur of foeHistory) {
|
|
if (valeur) {
|
|
nbTrue++;
|
|
} else {
|
|
nbFalse++;
|
|
}
|
|
}
|
|
if (nbTrue < nbFalse) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
class Party {
|
|
constructor(length, functions) {
|
|
this.length = length;
|
|
|
|
// if a list of active strategies is provided, use it,
|
|
// otherwise fall back to all seven by default
|
|
this.functions = (functions && functions.length > 0)
|
|
? functions
|
|
: [ALLC, ALLD, RAND, TFT, STFT, GRIM, MAJ];
|
|
|
|
this.grid = [];
|
|
|
|
for (let i = 0; i < this.length; i++) {
|
|
this.grid[i] = [];
|
|
|
|
for (let j = 0; j < this.length; j++) {
|
|
const index = Math.floor(Math.random() * this.functions.length);
|
|
this.grid[i][j] = this.functions[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
reset(functions) {
|
|
// if a new list of active strategies is passed, update it;
|
|
// otherwise keep the current selection
|
|
if (functions && functions.length > 0) {
|
|
this.functions = functions;
|
|
}
|
|
|
|
this.grid = [];
|
|
for (let i = 0; i < this.length; i++) {
|
|
this.grid[i] = [];
|
|
|
|
for (let j = 0; j < this.length; j++) {
|
|
const index = Math.floor(Math.random() * this.functions.length);
|
|
this.grid[i][j] = this.functions[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
step(T = 5, R = 3, P = 1, S = 0) {
|
|
const nbRound = 50;
|
|
|
|
let scores = [];
|
|
|
|
for (let i = 0; i < this.length; i++) {
|
|
scores[i] = [];
|
|
for (let j = 0; j < this.length; j++) {
|
|
scores[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
// computing scores
|
|
for (let i = 0; i < this.length; i++) {
|
|
for (let j = 0; j < this.length; j++) {
|
|
for (let di = -1; di < 2; di++) {
|
|
for (let dj = -1; dj < 2; dj ++) {
|
|
if (di !== 0 || dj !== 0) {
|
|
const ni = (i + di + this.length) % this.length;
|
|
const nj = (j + dj + this.length) % this.length;
|
|
|
|
let playerHist = [];
|
|
let playerStrat = this.grid[i][j];
|
|
|
|
let foeHist = [];
|
|
let foeStrat = this.grid[ni][nj];
|
|
|
|
for (let k = 0; k < nbRound; k++) {
|
|
let playerMove = playerStrat(foeHist);
|
|
let foeMove = foeStrat(playerHist);
|
|
|
|
playerHist.push(playerMove);
|
|
foeHist.push(foeMove);
|
|
|
|
if (playerMove && foeMove) { // both shared
|
|
scores[i][j] += R;
|
|
scores[ni][nj] += R;
|
|
} else if (playerMove && !foeMove) { // player lose
|
|
scores[i][j] += S;
|
|
scores[ni][nj] += T;
|
|
} else if (!playerMove && foeMove) { // foe lose
|
|
scores[i][j] += T;
|
|
scores[ni][nj] += S;
|
|
} else { // both lose
|
|
scores[i][j] += P;
|
|
scores[ni][nj] += P;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let newGrid = [];
|
|
|
|
for (let i = 0; i < this.length; i++) {
|
|
newGrid[i] = [];
|
|
for (let j = 0; j < this.length; j++) {
|
|
newGrid[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
// changing strats
|
|
for (let i = 0; i < this.length; i++) {
|
|
for (let j = 0; j < this.length; j++) {
|
|
let bestScore = scores[i][j];
|
|
newGrid[i][j] = this.grid[i][j];
|
|
for (let di = -1; di < 2; di++) {
|
|
for (let dj = -1; dj < 2; dj ++) {
|
|
if (di !== 0 || dj !== 0) {
|
|
const ni = (i + di + this.length) % this.length;
|
|
const nj = (j + dj + this.length) % this.length;
|
|
|
|
if (scores[ni][nj] > bestScore) { // someone has a better strategy
|
|
newGrid[i][j] = this.grid[ni][nj];
|
|
bestScore = scores[ni][nj];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
this.grid = newGrid;
|
|
}
|
|
} |