Show description
MAXWELL'S DEMON // ARCHITECT_BUILD
MAXWELL'S DEMON // ARCHITECT_BUILD
MAXWELL_DEMON.exe
SYS: ONLINE // 2ND_LAW: ACTIVE
Left Chamber (Cold Target)
000 K
Right Chamber (Hot Target)
000 K
Entropy Index
1.00
[ CLICK / TAP & HOLD TO OPEN SHUTTER ]
Mission Objective
Violate the Second Law of Thermodynamics. Use the shutter to sort the chaos.
1. Trap FAST particles on the RIGHT.
2. Trap SLOW particles on the LEFT.
Legend
*
High Energy (Fast)
o
Low Energy (Slow)
System Reset
MAXWELL'S DEMON // ARCHITECT_BUILD
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MAXWELL'S DEMON // ARCHITECT_BUILD</title>
<style>
:root {
--bg-core: #050505;
--term-orange: #ff7b00;
--term-white: #e0e0e0;
--term-dim: #444;
--font-mono: 'Courier New', Courier, monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; user-select: none; }
body {
background-color: var(--bg-core);
color: var(--term-white);
font-family: var(--font-mono);
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* --- CRT OVERLAY EFFECT --- */
body::after {
content: " ";
display: block;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
z-index: 10;
background-size: 100% 2px, 3px 100%;
pointer-events: none;
}
/* --- HEADER --- */
header {
border-bottom: 2px solid var(--term-dim);
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
background: #000;
z-index: 2;
}
h1 {
font-size: 1.2rem;
color: var(--term-orange);
text-transform: uppercase;
letter-spacing: 2px;
}
.status {
font-size: 0.8rem;
color: var(--term-dim);
}
/* --- MAIN LAYOUT --- */
main {
flex: 1;
display: flex;
position: relative;
}
.simulation-container {
flex: 1;
position: relative;
background: #000;
cursor: crosshair;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
/* --- HUD --- */
.hud {
position: absolute;
top: 20px;
left: 20px;
pointer-events: none;
display: flex;
gap: 40px;
}
.hud-block {
background: rgba(0,0,0,0.8);
border: 1px solid var(--term-dim);
padding: 10px;
min-width: 150px;
}
.hud-label {
display: block;
font-size: 0.7rem;
color: var(--term-dim);
margin-bottom: 5px;
text-transform: uppercase;
}
.hud-value {
font-size: 1.5rem;
font-weight: bold;
}
.orange-text { color: var(--term-orange); }
.white-text { color: var(--term-white); }
/* --- INTERACTION HINT --- */
.hint {
position: absolute;
bottom: 30px;
width: 100%;
text-align: center;
color: var(--term-dim);
font-size: 0.8rem;
animation: blink 2s infinite;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
/* --- SIDEBAR INFO --- */
aside {
width: 300px;
border-left: 2px solid var(--term-dim);
padding: 1.5rem;
background: #080808;
display: flex;
flex-direction: column;
justify-content: space-between;
z-index: 5;
}
.info-block h3 {
color: var(--term-orange);
font-size: 0.9rem;
margin-bottom: 0.5rem;
text-transform: uppercase;
border-bottom: 1px dashed var(--term-dim);
padding-bottom: 5px;
}
.info-block p {
font-size: 0.8rem;
line-height: 1.4;
color: #aaa;
margin-bottom: 1.5rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
font-size: 0.8rem;
}
.char-icon {
font-weight: bold;
font-size: 1.2rem;
width: 20px;
text-align: center;
}
.btn {
background: transparent;
border: 1px solid var(--term-orange);
color: var(--term-orange);
padding: 10px;
font-family: var(--font-mono);
cursor: pointer;
text-transform: uppercase;
transition: 0.2s;
}
.btn:hover {
background: var(--term-orange);
color: #000;
}
/* MOBILE */
@media (max-width: 800px) {
main { flex-direction: column; }
aside { width: 100%; height: 200px; overflow-y: scroll; border-left: none; border-top: 2px solid var(--term-dim); }
.hud { transform: scale(0.8); transform-origin: top left; }
}
</style>
</head>
<body>
<header>
<h1>MAXWELL_DEMON.exe</h1>
<div class="status">SYS: ONLINE // 2ND_LAW: ACTIVE</div>
</header>
<main>
<div class="simulation-container" id="simContainer">
<canvas id="simCanvas"></canvas>
<div class="hud">
<div class="hud-block">
<span class="hud-label">Left Chamber (Cold Target)</span>
<span class="hud-value white-text" id="tempLeft">000 K</span>
</div>
<div class="hud-block">
<span class="hud-label">Right Chamber (Hot Target)</span>
<span class="hud-value orange-text" id="tempRight">000 K</span>
</div>
<div class="hud-block">
<span class="hud-label">Entropy Index</span>
<span class="hud-value" id="entropyDisplay">1.00</span>
</div>
</div>
<div class="hint">[ CLICK / TAP & HOLD TO OPEN SHUTTER ]</div>
</div>
<aside>
<div class="info-block">
<h3>Mission Objective</h3>
<p>
Violate the Second Law of Thermodynamics. Use the shutter to sort the chaos.
<br><br>
1. Trap <strong>FAST</strong> particles on the <strong>RIGHT</strong>.
<br>
2. Trap <strong>SLOW</strong> particles on the <strong>LEFT</strong>.
</p>
<h3>Legend</h3>
<div class="legend-item">
<span class="char-icon orange-text">*</span>
<span>High Energy (Fast)</span>
</div>
<div class="legend-item">
<span class="char-icon white-text">o</span>
<span>Low Energy (Slow)</span>
</div>
</div>
<button class="btn" onclick="resetSim()">System Reset</button>
</aside>
</main>
<script>
const canvas = document.getElementById('simCanvas');
const ctx = canvas.getContext('2d');
const container = document.getElementById('simContainer');
// --- CONFIG ---
const PARTICLE_COUNT = 60;
const SPEED_FAST = 4;
const SPEED_SLOW = 1.5;
const RADIUS = 8;
let width, height;
let particles = [];
let isShutterOpen = false;
let midX = 0;
// UI Elements
const uiLeft = document.getElementById('tempLeft');
const uiRight = document.getElementById('tempRight');
const uiEntropy = document.getElementById('entropyDisplay');
// --- CLASSES ---
class Particle {
constructor() {
this.reset();
}
reset() {
this.x = Math.random() * (width - 20) + 10;
this.y = Math.random() * (height - 20) + 10;
// Randomly assign type (Hot or Cold)
this.isHot = Math.random() > 0.5;
const speed = this.isHot ? SPEED_FAST : SPEED_SLOW;
const angle = Math.random() * Math.PI * 2;
this.vx = Math.cos(angle) * speed;
this.vy = Math.sin(angle) * speed;
// Add some random variation so they aren't identical
this.vx += (Math.random() - 0.5) * 0.5;
this.vy += (Math.random() - 0.5) * 0.5;
this.char = this.isHot ? '*' : 'o';
this.color = this.isHot ? '#ff7b00' : '#e0e0e0';
}
update() {
this.x += this.vx;
this.y += this.vy;
// Wall Collisions (Outer)
if (this.x < RADIUS) { this.x = RADIUS; this.vx *= -1; }
if (this.x > width - RADIUS) { this.x = width - RADIUS; this.vx *= -1; }
if (this.y < RADIUS) { this.y = RADIUS; this.vy *= -1; }
if (this.y > height - RADIUS) { this.y = height - RADIUS; this.vy *= -1; }
// The Demon's Wall (Middle)
// The wall is at midX. It has a gap if isShutterOpen is true.
// We simplify: if shutter is open, no X collision check near middle.
// If shutter is closed, bounce off midX.
if (!isShutterOpen) {
// Check if hitting the middle wall
// We need to know which side we were on previously to bounce correctly
// Simple check: predicted position crossing midX
// Particle radius buffer
const buffer = RADIUS + 2;
// Hitting from Left
if (this.x + RADIUS > midX - 2 && this.x < midX && this.vx > 0) {
this.x = midX - buffer;
this.vx *= -1;
}
// Hitting from Right
else if (this.x - RADIUS < midX + 2 && this.x > midX && this.vx < 0) {
this.x = midX + buffer;
this.vx *= -1;
}
}
}
draw() {
ctx.fillStyle = this.color;
ctx.font = this.isHot ? "20px monospace" : "16px monospace";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(this.char, this.x, this.y);
}
}
// --- ENGINE ---
function init() {
resize();
particles = [];
for (let i = 0; i < PARTICLE_COUNT; i++) {
particles.push(new Particle());
}
animate();
}
function resize() {
width = container.clientWidth;
height = container.clientHeight;
canvas.width = width;
canvas.height = height;
midX = width / 2;
}
function calculateStats() {
let leftTotalSpeed = 0;
let leftCount = 0;
let rightTotalSpeed = 0;
let rightCount = 0;
// Entropy Factors
let hotRight = 0;
let coldLeft = 0;
particles.forEach(p => {
const speed = Math.sqrt(p.vx*p.vx + p.vy*p.vy);
if (p.x < midX) {
leftTotalSpeed += speed;
leftCount++;
if (!p.isHot) coldLeft++;
} else {
rightTotalSpeed += speed;
rightCount++;
if (p.isHot) hotRight++;
}
});
// Avoid divide by zero
const tempL = leftCount > 0 ? (leftTotalSpeed / leftCount) * 100 : 0;
const tempR = rightCount > 0 ? (rightTotalSpeed / rightCount) * 100 : 0;
uiLeft.innerText = Math.round(tempL) + " K";
uiRight.innerText = Math.round(tempR) + " K";
// Simplified Entropy Metric (Orderliness)
// 0.0 = Totally Ordered (Win state), 1.0 = Random
// Max order = all hot right (count/2), all cold left (count/2)
const correctParticles = hotRight + coldLeft;
const orderRatio = correctParticles / PARTICLE_COUNT;
// Invert for "Entropy" (Disorder)
// If orderRatio is 1 (perfect sort), Entropy is 0.
// If orderRatio is 0.5 (random mix), Entropy is High.
// Mapping 0.5 -> 1.0 (High Entropy) and 1.0 -> 0.0 (Low Entropy) is tricky because 0.5 is the baseline average.
// Let's just map "Sorted %".
let entropyVal = 1 - ((orderRatio - 0.5) * 2);
// If orderRatio is 0.5 (random), result is 1.0.
// If orderRatio is 1.0 (sorted), result is 0.0.
if(entropyVal > 1) entropyVal = 1;
if(entropyVal < 0) entropyVal = 0;
uiEntropy.innerText = entropyVal.toFixed(2);
// Color Logic for UI
if (entropyVal < 0.3) {
uiEntropy.style.color = "#00ff00"; // Winning
uiEntropy.innerText += " [CRITICAL ORDER]";
} else {
uiEntropy.style.color = "var(--term-white)";
}
}
function drawWall() {
ctx.fillStyle = isShutterOpen ? "#333" : "#888";
ctx.font = "20px monospace";
ctx.textAlign = "center";
// Draw a vertical line of ASCII characters
const char = isShutterOpen ? ":" : "|";
const gap = 25;
for (let y = 0; y < height; y += gap) {
// If open, maybe don't draw the middle section?
// Let's just dim it to signify "Passable"
ctx.fillText(char, midX, y);
}
// Draw Label
ctx.fillStyle = "#fff";
ctx.font = "10px monospace";
ctx.fillText(isShutterOpen ? "GATE OPEN" : "GATE CLOSED", midX, height - 20);
}
function animate() {
// Clear Background
ctx.fillStyle = "#050505";
ctx.fillRect(0, 0, width, height);
// Draw Grid (Subtle)
ctx.strokeStyle = "#111";
ctx.lineWidth = 1;
ctx.beginPath();
for(let x=0; x<width; x+=50) { ctx.moveTo(x,0); ctx.lineTo(x,height); }
for(let y=0; y<height; y+=50) { ctx.moveTo(0,y); ctx.lineTo(width,y); }
ctx.stroke();
drawWall();
particles.forEach(p => {
p.update();
p.draw();
});
calculateStats();
requestAnimationFrame(animate);
}
// --- CONTROLS ---
function openShutter() { isShutterOpen = true; }
function closeShutter() { isShutterOpen = false; }
function resetSim() {
particles.forEach(p => p.reset());
}
// Mouse / Touch
container.addEventListener('mousedown', openShutter);
container.addEventListener('mouseup', closeShutter);
container.addEventListener('touchstart', (e) => { e.preventDefault(); openShutter(); });
container.addEventListener('touchend', (e) => { e.preventDefault(); closeShutter(); });
// Window Resize
window.addEventListener('resize', resize);
// Start
window.onload = init;
</script>
</body>
</html>