dilemmap/main.js
2026-07-25 23:04:05 +02:00

188 lines
No EOL
5.7 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];
}
}
}
}
}
}
// a random cell change
let ni = Math.floor(Math.random() * this.length);
let nj = Math.floor(Math.random() * this.length);
const index = Math.floor(Math.random() * this.functions.length);
newGrid[ni][nj] = this.functions[index];
this.grid = newGrid;
this.grid = newGrid;
}
}