Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
398 lines
12 KiB
HTML
398 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>404 - Navigate the Labyrinth</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
width: 100%;
|
||
height: 100vh;
|
||
font-family: 'Arial', sans-serif;
|
||
background: #000;
|
||
color: #fff;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
overflow: hidden;
|
||
}
|
||
|
||
#game-container {
|
||
width: 100%;
|
||
height: 100%;
|
||
position: relative;
|
||
background: #000;
|
||
}
|
||
|
||
canvas {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.hud {
|
||
position: absolute;
|
||
top: 20px;
|
||
left: 20px;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
border: 2px solid #ffff00;
|
||
padding: 15px 25px;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 18px;
|
||
z-index: 10;
|
||
box-shadow: inset 0 0 10px rgba(255, 255, 0, 0.3);
|
||
}
|
||
|
||
.hud h1 {
|
||
color: #ff0000;
|
||
font-size: 32px;
|
||
margin-bottom: 10px;
|
||
text-shadow: 0 0 10px #ff0000;
|
||
}
|
||
|
||
.hud p {
|
||
color: #ffff00;
|
||
margin: 5px 0;
|
||
}
|
||
|
||
.help-text {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: rgba(0, 0, 0, 0.8);
|
||
border: 2px solid #ffff00;
|
||
padding: 10px 20px;
|
||
text-align: center;
|
||
font-family: 'Courier New', monospace;
|
||
z-index: 10;
|
||
max-width: 90%;
|
||
}
|
||
|
||
.help-text p {
|
||
margin: 5px 0;
|
||
color: #ffff00;
|
||
}
|
||
|
||
.controls {
|
||
color: #00ff00;
|
||
font-size: 14px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.loading {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
text-align: center;
|
||
z-index: 20;
|
||
color: #ffff00;
|
||
font-family: 'Courier New', monospace;
|
||
}
|
||
|
||
.loading h2 {
|
||
font-size: 28px;
|
||
margin-bottom: 20px;
|
||
text-shadow: 0 0 10px #ffff00;
|
||
}
|
||
|
||
.progress-bar {
|
||
width: 300px;
|
||
height: 30px;
|
||
border: 2px solid #ffff00;
|
||
background: #000;
|
||
position: relative;
|
||
margin: 20px auto;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.progress {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, #ff0000, #ffff00, #00ff00);
|
||
width: 0%;
|
||
transition: width 0.1s;
|
||
}
|
||
|
||
.welcome {
|
||
position: absolute;
|
||
top: 60px;
|
||
right: 20px;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
border: 2px solid #ff0000;
|
||
padding: 15px 20px;
|
||
font-family: 'Courier New', monospace;
|
||
z-index: 10;
|
||
max-width: 300px;
|
||
text-align: right;
|
||
}
|
||
|
||
.welcome h3 {
|
||
color: #ff0000;
|
||
margin-bottom: 10px;
|
||
font-size: 16px;
|
||
text-shadow: 0 0 10px #ff0000;
|
||
}
|
||
|
||
.welcome p {
|
||
color: #ffff00;
|
||
font-size: 12px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.hud {
|
||
top: 10px;
|
||
left: 10px;
|
||
padding: 10px 15px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.hud h1 {
|
||
font-size: 24px;
|
||
}
|
||
|
||
.welcome {
|
||
display: none;
|
||
}
|
||
|
||
.help-text {
|
||
font-size: 12px;
|
||
padding: 8px 15px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="game-container">
|
||
<canvas id="doom-canvas"></canvas>
|
||
|
||
<div class="hud">
|
||
<h1>4️⃣ 0️⃣ 4</h1>
|
||
<p>PAGE NOT FOUND</p>
|
||
<p>⚠️ DEMON INVASION IN PROGRESS</p>
|
||
<div class="controls">
|
||
<p>↑↓←→ or WASD - MOVE</p>
|
||
<p>MOUSE - LOOK AROUND</p>
|
||
<p>CLICK - SHOOT</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="welcome">
|
||
<h3>🔥 WELCOME TO</h3>
|
||
<p>DOOM SHAREWARE v1.9</p>
|
||
<p style="margin-top: 10px; font-size: 11px; color: #00ff00;">The page you seek has been consumed by demons. Fight your way through Hell to find it...</p>
|
||
</div>
|
||
|
||
<div class="help-text">
|
||
<p><strong>🎮 USE ARROW KEYS OR WASD TO MOVE • MOUSE TO AIM • CLICK TO SHOOT</strong></p>
|
||
<p style="font-size: 12px; margin-top: 5px;">⬅️ Press <strong>ESC</strong> to return home</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="loading" id="loading">
|
||
<h2>⚙️ INITIALIZING GAME</h2>
|
||
<div class="progress-bar">
|
||
<div class="progress" id="progress"></div>
|
||
</div>
|
||
<p id="loading-text">Loading WAD... 0%</p>
|
||
</div>
|
||
|
||
<!-- WAD.js - Doom engine for web -->
|
||
<script src="https://cdn.jsdelivr.net/npm/js-dos@7.9.1/js-dos.js"></script>
|
||
|
||
<script>
|
||
// Initialize Doom game
|
||
const canvas = document.getElementById('doom-canvas');
|
||
const loadingDiv = document.getElementById('loading');
|
||
const progressBar = document.getElementById('progress');
|
||
const loadingText = document.getElementById('loading-text');
|
||
|
||
// Simple Doom-like game canvas rendering
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
function resizeCanvas() {
|
||
canvas.width = window.innerWidth;
|
||
canvas.height = window.innerHeight;
|
||
}
|
||
|
||
resizeCanvas();
|
||
window.addEventListener('resize', resizeCanvas);
|
||
|
||
// Create a simple doom-like raycasting effect
|
||
class SimpleDoom {
|
||
constructor(canvas) {
|
||
this.canvas = canvas;
|
||
this.ctx = canvas.getContext('2d');
|
||
this.width = canvas.width;
|
||
this.height = canvas.height;
|
||
|
||
this.playerX = 32;
|
||
this.playerY = 32;
|
||
this.playerAngle = 0;
|
||
this.keys = {};
|
||
this.mouseX = 0;
|
||
this.mouseY = 0;
|
||
this.mouseDown = false;
|
||
|
||
this.setupInput();
|
||
this.gameLoop();
|
||
}
|
||
|
||
setupInput() {
|
||
document.addEventListener('keydown', (e) => {
|
||
this.keys[e.key.toLowerCase()] = true;
|
||
if (e.key === 'Escape') {
|
||
window.location.href = '/';
|
||
}
|
||
});
|
||
|
||
document.addEventListener('keyup', (e) => {
|
||
this.keys[e.key.toLowerCase()] = false;
|
||
});
|
||
|
||
document.addEventListener('mousemove', (e) => {
|
||
this.mouseX = e.clientX;
|
||
this.mouseY = e.clientY;
|
||
});
|
||
|
||
document.addEventListener('mousedown', () => {
|
||
this.mouseDown = true;
|
||
});
|
||
|
||
document.addEventListener('mouseup', () => {
|
||
this.mouseDown = false;
|
||
});
|
||
}
|
||
|
||
update() {
|
||
const speed = 2;
|
||
const rotSpeed = 0.05;
|
||
|
||
if (this.keys['arrowup'] || this.keys['w']) {
|
||
this.playerX += Math.cos(this.playerAngle) * speed;
|
||
this.playerY += Math.sin(this.playerAngle) * speed;
|
||
}
|
||
if (this.keys['arrowdown'] || this.keys['s']) {
|
||
this.playerX -= Math.cos(this.playerAngle) * speed;
|
||
this.playerY -= Math.sin(this.playerAngle) * speed;
|
||
}
|
||
if (this.keys['arrowleft'] || this.keys['a']) {
|
||
this.playerAngle -= rotSpeed;
|
||
}
|
||
if (this.keys['arrowright'] || this.keys['d']) {
|
||
this.playerAngle += rotSpeed;
|
||
}
|
||
|
||
// Mouse look
|
||
if (this.mouseDown) {
|
||
this.playerAngle = (this.mouseX / this.width) * Math.PI * 2;
|
||
}
|
||
}
|
||
|
||
render() {
|
||
// Sky
|
||
this.ctx.fillStyle = '#440000';
|
||
this.ctx.fillRect(0, 0, this.width, this.height / 2);
|
||
|
||
// Floor
|
||
this.ctx.fillStyle = '#220000';
|
||
this.ctx.fillRect(0, this.height / 2, this.width, this.height / 2);
|
||
|
||
// Simple raycasting
|
||
const rays = 120;
|
||
const rayWidth = this.width / rays;
|
||
|
||
for (let i = 0; i < rays; i++) {
|
||
const rayAngle = this.playerAngle - (Math.PI / 3) + (i / rays) * (Math.PI / 1.5);
|
||
|
||
// Simple distance calculation
|
||
const distance = Math.sin(i * 0.05) * 100 + 50;
|
||
const wallHeight = Math.max(10, (this.height / distance) * 50);
|
||
|
||
// Wall color based on angle
|
||
const hue = (rayAngle * 180 / Math.PI) % 360;
|
||
const brightness = Math.sin(i * 0.02) * 0.3 + 0.5;
|
||
|
||
// Create doom-like color palette
|
||
let color = '#ff0000';
|
||
if (distance < 100) {
|
||
color = `rgb(${Math.floor(255 * brightness)}, 0, 0)`;
|
||
} else if (distance < 150) {
|
||
color = `rgb(${Math.floor(100 * brightness)}, 0, 0)`;
|
||
} else {
|
||
color = `rgb(${Math.floor(50 * brightness)}, 0, 0)`;
|
||
}
|
||
|
||
this.ctx.fillStyle = color;
|
||
this.ctx.fillRect(i * rayWidth, (this.height - wallHeight) / 2, rayWidth + 1, wallHeight);
|
||
}
|
||
|
||
// Draw HUD elements
|
||
this.drawHUD();
|
||
}
|
||
|
||
drawHUD() {
|
||
// Ammo counter
|
||
this.ctx.fillStyle = '#ffff00';
|
||
this.ctx.font = 'bold 16px Courier New';
|
||
this.ctx.fillText('AMMO: 999', 20, this.height - 20);
|
||
|
||
// Health
|
||
this.ctx.fillText('HEALTH: 100%', this.width - 200, this.height - 20);
|
||
|
||
// Weapon indicator (moving crosshair effect)
|
||
const crossX = this.mouseX || this.width / 2;
|
||
const crossY = this.mouseY || this.height / 2;
|
||
|
||
this.ctx.strokeStyle = '#ffff00';
|
||
this.ctx.lineWidth = 2;
|
||
this.ctx.beginPath();
|
||
this.ctx.moveTo(crossX - 20, crossY);
|
||
this.ctx.lineTo(crossX + 20, crossY);
|
||
this.ctx.moveTo(crossX, crossY - 20);
|
||
this.ctx.lineTo(crossX, crossY + 20);
|
||
this.ctx.stroke();
|
||
}
|
||
|
||
gameLoop() {
|
||
this.update();
|
||
this.render();
|
||
requestAnimationFrame(() => this.gameLoop());
|
||
}
|
||
}
|
||
|
||
// Update loading progress
|
||
function updateProgress(percent) {
|
||
progressBar.style.width = percent + '%';
|
||
loadingText.textContent = `Loading WAD... ${percent}%`;
|
||
}
|
||
|
||
// Simulate loading
|
||
let progress = 0;
|
||
const loadingInterval = setInterval(() => {
|
||
progress += Math.random() * 30;
|
||
if (progress > 90) progress = 90;
|
||
updateProgress(Math.floor(progress));
|
||
}, 300);
|
||
|
||
// Start game after brief loading animation
|
||
setTimeout(() => {
|
||
clearInterval(loadingInterval);
|
||
updateProgress(100);
|
||
|
||
setTimeout(() => {
|
||
loadingDiv.style.display = 'none';
|
||
const game = new SimpleDoom(canvas);
|
||
}, 800);
|
||
}, 2000);
|
||
</script>
|
||
</body>
|
||
</html>
|