version fonctionelle
This commit is contained in:
parent
f372fcc6cd
commit
268e073a4a
2 changed files with 248 additions and 0 deletions
156
index.html
156
index.html
|
|
@ -0,0 +1,156 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Strategy Grid</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stepBtn {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 6px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1px;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#legend {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-color {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #333;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>Strategy Grid</h1>
|
||||||
|
<div id="controls">
|
||||||
|
<button id="stepBtn">Step</button>
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<div id="grid"></div>
|
||||||
|
<div id="legend"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="main.js"></script>
|
||||||
|
<script>
|
||||||
|
// This file only handles rendering.
|
||||||
|
// ALLC, ALLD, RAND, TFT, GRIM, MAJ and the Party class
|
||||||
|
// are already defined in script.js and are not redefined here.
|
||||||
|
|
||||||
|
// ---- Color / function mapping ----
|
||||||
|
|
||||||
|
const COLORS = {
|
||||||
|
allwaysCooperate: "#2ecc71", // green
|
||||||
|
allwaysDefect: "#e74c3c", // red
|
||||||
|
randomChoice: "#95a5a6", // gray
|
||||||
|
titForThat: "#3498db", // blue
|
||||||
|
grimTrigger: "#8e44ad", // purple
|
||||||
|
majority: "#f39c12" // orange
|
||||||
|
};
|
||||||
|
|
||||||
|
const LABELS = {
|
||||||
|
allwaysCooperate: "Always Cooperate",
|
||||||
|
allwaysDefect: "Always Defect",
|
||||||
|
randomChoice: "Random",
|
||||||
|
titForThat: "Tit-for-Tat",
|
||||||
|
grimTrigger: "Grim Trigger",
|
||||||
|
majority: "Majority"
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---- Rendering ----
|
||||||
|
|
||||||
|
function renderGrid(party) {
|
||||||
|
const gridEl = document.getElementById("grid");
|
||||||
|
gridEl.innerHTML = "";
|
||||||
|
gridEl.style.gridTemplateColumns = `repeat(${party.length}, 12px)`;
|
||||||
|
|
||||||
|
for (let i = 0; i < party.length; i++) {
|
||||||
|
for (let j = 0; j < party.length; j++) {
|
||||||
|
const fn = party.grid[i][j];
|
||||||
|
const cell = document.createElement("div");
|
||||||
|
cell.className = "cell";
|
||||||
|
cell.style.backgroundColor = COLORS[fn.name] || "#000";
|
||||||
|
cell.title = LABELS[fn.name] || fn.name;
|
||||||
|
gridEl.appendChild(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderLegend() {
|
||||||
|
const legendEl = document.getElementById("legend");
|
||||||
|
for (const key in COLORS) {
|
||||||
|
const item = document.createElement("div");
|
||||||
|
item.className = "legend-item";
|
||||||
|
|
||||||
|
const colorBox = document.createElement("span");
|
||||||
|
colorBox.className = "legend-color";
|
||||||
|
colorBox.style.backgroundColor = COLORS[key];
|
||||||
|
|
||||||
|
const label = document.createElement("span");
|
||||||
|
label.textContent = LABELS[key];
|
||||||
|
|
||||||
|
item.appendChild(colorBox);
|
||||||
|
item.appendChild(label);
|
||||||
|
legendEl.appendChild(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Execution ----
|
||||||
|
|
||||||
|
const party = new Party(60);
|
||||||
|
renderGrid(party);
|
||||||
|
renderLegend();
|
||||||
|
|
||||||
|
document.getElementById("stepBtn").addEventListener("click", () => {
|
||||||
|
party.step();
|
||||||
|
renderGrid(party);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
92
main.js
92
main.js
|
|
@ -61,4 +61,96 @@ class Party {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
step() {
|
||||||
|
const T = 5;
|
||||||
|
const R = 3;
|
||||||
|
const P = 1;
|
||||||
|
const 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 strarts
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue