Skip to content
LAM
Read Home Blog
Make Projects HTML Tools Games
Touch grass Notes Resume Links
Home Blog HTML Projects
Tools Games Notes Resume Links
Back MAXWELL'S DEMON // ARCHITECT_BUILD Thermodynamics
Download Open
Show description 540 chars · Thermodynamics

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

16,475 bytes · HTML source
<!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>