Skip to content

Instantly share code, notes, and snippets.

@franklinbaldo
Created November 16, 2024 03:33
Show Gist options
  • Save franklinbaldo/658344f4fd284afeed704e785ee923d5 to your computer and use it in GitHub Desktop.
Save franklinbaldo/658344f4fd284afeed704e785ee923d5 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Simulação do Dilema do Prisioneiro</title>
<style>
canvas {
border: 1px solid black;
background-color: #f0f0f0;
}
#scoreboard {
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Simulação do Dilema do Prisioneiro com Agentes</h1>
<canvas id="canvas" width="800" height="600"></canvas>
<div id="scoreboard"></div>
<script>
// Obter o contexto do canvas
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Definir a matriz de payoff
const payoffMatrix = {
'CC': [3, 3],
'CD': [0, 5],
'DC': [5, 0],
'DD': [1, 1]
};
// Estratégias possíveis
const strategies = ['Sempre Cooperar', 'Sempre Trair', 'Aleatório', 'Tit for Tat'];
// Classe Agente
class Agent {
constructor(id, x, y, strategy) {
this.id = id;
this.x = x;
this.y = y;
this.strategy = strategy;
this.score = 0;
this.dx = (Math.random() - 0.5) * 2; // Velocidade aleatória entre -1 e 1
this.dy = (Math.random() - 0.5) * 2;
this.size = 5; // Tamanho do agente
this.history = {}; // Histórico de interações
}
move() {
this.x += this.dx;
this.y += this.dy;
// Rebater nas bordas
if (this.x <= 0 || this.x >= canvas.width) this.dx *= -1;
if (this.y <= 0 || this.y >= canvas.height) this.dy *= -1;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fillStyle = this.getColor();
ctx.fill();
}
getColor() {
switch (this.strategy) {
case 'Sempre Cooperar':
return 'green';
case 'Sempre Trair':
return 'red';
case 'Aleatório':
return 'orange';
case 'Tit for Tat':
return 'blue';
default:
return 'black';
}
}
}
// Funções de estratégia
function alwaysCooperate() {
return 'C';
}
function alwaysDefect() {
return 'D';
}
function randomStrategy() {
return Math.random() < 0.5 ? 'C' : 'D';
}
function titForTat(opponentHistory) {
if (opponentHistory && opponentHistory.length > 0) {
return opponentHistory[opponentHistory.length - 1];
} else {
return 'C';
}
}
// Criar agentes
const agents = [];
const numAgents = 50;
for (let i = 0; i < numAgents; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
const strategy = strategies[Math.floor(Math.random() * strategies.length)];
agents.push(new Agent(i, x, y, strategy));
}
// Função para jogar o Dilema do Prisioneiro
function playGame(agent1, agent2) {
let move1, move2;
// Determinar o movimento do agente 1
if (agent1.strategy === 'Sempre Cooperar') {
move1 = alwaysCooperate();
} else if (agent1.strategy === 'Sempre Trair') {
move1 = alwaysDefect();
} else if (agent1.strategy === 'Aleatório') {
move1 = randomStrategy();
} else if (agent1.strategy === 'Tit for Tat') {
move1 = titForTat(agent2.history[agent1.id]);
}
// Determinar o movimento do agente 2
if (agent2.strategy === 'Sempre Cooperar') {
move2 = alwaysCooperate();
} else if (agent2.strategy === 'Sempre Trair') {
move2 = alwaysDefect();
} else if (agent2.strategy === 'Aleatório') {
move2 = randomStrategy();
} else if (agent2.strategy === 'Tit for Tat') {
move2 = titForTat(agent1.history[agent2.id]);
}
// Atualizar históricos
if (!agent1.history[agent2.id]) agent1.history[agent2.id] = [];
if (!agent2.history[agent1.id]) agent2.history[agent1.id] = [];
agent1.history[agent2.id].push(move1);
agent2.history[agent1.id].push(move2);
// Obter os payoffs
const key = move1 + move2;
const [score1, score2] = payoffMatrix[key];
agent1.score += score1;
agent2.score += score2;
}
// Função de detecção de colisão
function detectCollisions() {
for (let i = 0; i < agents.length; i++) {
for (let j = i + 1; j < agents.length; j++) {
const dx = agents[i].x - agents[j].x;
const dy = agents[i].y - agents[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < agents[i].size + agents[j].size) {
playGame(agents[i], agents[j]);
}
}
}
}
// Atualizar o quadro
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Mover e desenhar agentes
agents.forEach(agent => {
agent.move();
agent.draw(ctx);
});
// Detectar colisões e jogar
detectCollisions();
// Atualizar placar
updateScoreboard();
requestAnimationFrame(update);
}
// Atualizar o placar
function updateScoreboard() {
const scoreboard = document.getElementById('scoreboard');
let html = '<h2>Placar</h2>';
strategies.forEach(strategy => {
const totalScore = agents
.filter(agent => agent.strategy === strategy)
.reduce((sum, agent) => sum + agent.score, 0);
const count = agents.filter(agent => agent.strategy === strategy).length;
html += `<p><strong>${strategy}:</strong> Pontuação Total = ${totalScore.toFixed(2)}, Número de Agentes = ${count}</p>`;
});
scoreboard.innerHTML = html;
}
// Iniciar a simulação
update();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment