Add D&D labyrinth at /dndlabyrinth/

Already live on the server via rsync; bringing the repo in sync.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric WagonerandClaude Fable 5 committed 2026-11-10 20:02:22 -05:00
1 parent db156f3227
commit 1b9e6e32d8
38 files changed
+1760

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
# Dungeons &amp; Dragons&trade; Computer Labyrinth Game Simulator
## Version 1.1
This game is a simulation of the Mattel Electronics&trade; Dungeons and Dragons&trade; Computer Labyrinth Game
![Mattel Electronics&trade; Dungeons and Dragons&trade; Computer Labyrinth Game](images/featuredImage.jpg)
<sub><sup>Images of the game, the manual, game pieces, artwork and any audio are copyright of [Mattel](https://www.mattel.com/en-us)&trade;. Dungeons and Dragons&trade; is copyright of [Wizards of the Coast](https://company.wizards.com/)&trade;.</sup></sub>
## Background
While browsing on Facebook I came across a post on a friend's feed about a 1980 Mattel Electronics&trade; Dungeons and Dragons&trade; Computer Labyrinth Game. At the time the game looked vaguely familiar but as I read through the post all the memories came back to me. I remembered owning this game when I was about 11 and being fascinated by it. Being a software developer I couldn't help but to try and recreate it.
## Technical Info
This repo consists of an HTML5 page with a simulation of the game built on Javascript and CSS. It is entirely built in native Javascript so no other packages or libraries are required. The styles are also all written in native CSS so no SCSS/SASS compilers are needed. The HTML, styles and code are all unobfuscated and unminified as I use Cloudflare to perform the caching and minification.
### Browser Support
All modern browsers running ECMAScript 2015 ES6 should be able to run the game. If the game detects that the Javascript `Promise` or `URL` objects do not exist it assumes the browser is not capable of supporting the game and alerts the user.
## Game Play
The original game required the user to place and move the game pieces but to make this simulation easier to play, I have the game pieces being placed and moved automatically. Time permitting I may add a "classic" mode later that would rely on the user to manually place and move all the game pieces to make it more like the original game. A [PDF User Manual](./assets/gameManual.pdf) describing the game is also included.
## Licensing
### MIT License
Copyright&copy; 2021 Bob Whitley
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+420
View File
@@ -0,0 +1,420 @@
@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
html {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
padding: 0;
background-color: black;
display: flex;
flex-direction: column;
flex: 1;
min-height: 100%;
touch-action: manipulation;
}
body {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
padding: 0;
background-color: black;
color: rgb(203 203 203);
display: flex;
flex: 1;
justify-content: center;
font-size: 14px;
}
input {
font-size: 14px;
}
button {
font-size: 14px;
}
body.play {
overflow: hidden;
}
main {
margin: 0;
padding: 0;
position: relative;
}
body.play main {
display: flex;
flex-direction: column;
flex: 1;
}
a, a:visited, a:active {
color: #fff;
text-decoration: underline;;
}
a:hover, a:active {
color: rgb(185 54 61);
}
#intro {
display: flex;
flex-direction: column;
margin: 0 auto;
overflow: hidden;
max-width: 640px;
max-height: 1000px;
text-align: center;
opacity: 1;
padding: 20px 20px;
transition: max-height 250ms, opacity 250ms, padding 250ms;
}
body.play #intro {
border: solid 0 transparent;
opacity: 0;
max-height: 0;
padding: 0;
}
#intro #header {
border: solid 3px rgb(185 54 61);
border-radius: 10px;
padding: 5px 50px;
background: #242424;
text-shadow: 3px 3px 1px rgb(0 0 0);
margin: 0 auto 30px auto;
display: inline-block;
background-image: url('../images/dragonBackground.jpg');
background-size: cover;
background-position: center;
}
#intro #header h1 {
font-family: MedievalSharp;
color: #fff;
font-size: 1.4em;
font-weight: 700;
line-height: 1.3em;
}
#intro .subtext {
color: #999;
font-size: .75em;
}
#intro .subtext a {
color: #999
}
#intro .subtext a:hover, a:active {
color: rgb(185 54 61);
}
#intro .subtext a:hover, a:active {
color: rgb(185 54 61);
}
#container {
position: relative;
display: block;
width: 90vmin;
height: 30%;
margin: 0 auto;
transition: width 250ms, height 250ms, margin 250ms;
}
body.play #container {
height: 90vmin;
margin: auto;
}
#start {
display: flex;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10000;
background-color: rgba(0,0,0,.7);
text-align: center;
cursor: pointer;
align-content: center;
justify-content: center;
}
#start .text {
background-color: 242424;
padding: 10px 15px;
border-radius: 5px;
font-weight: 700;
border: solid 3px rgb(185 54 61);
z-index: 10001;
box-shadow: 0px 0px 20px 5px black;
display: inline-block;
margin: auto;
font-family: 'MedievalSharp';
text-shadow: 3px 3px 1px rgb(0 0 0);
vertical-align: middle;
letter-spacing: normal;
color: #fff;
}
body.play #start {
display: none;
}
#board {
width: 100%;
height: 100%;
position: relative;
display: flex;
margin: 0;
background-image: url('../images/board.jpg');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
transition: width 250ms ease-in-out, height 250ms ease-in-out, margin 250ms ease-in-out;
}
body.play #home {
display: flex;
}
#menu {
display: none;
flex-direction: row;
position: fixed;
top: 5px;
right: 5px;
left: 5px;
padding: 5px;
align-items: center;
color: #bebebe;
}
#menuLeft {
display: flex;
width: 30%;
justify-content: flex-start;
}
#menuCenter {
display: flex;
flex: 1;
justify-content: center;
}
#menuRight {
display: flex;
width: 30%;
justify-content: flex-end;
}
#menu a, #menu a:visited {
text-decoration: none;
cursor: pointer;
color: #bebebe;
}
#menu a:hover, #menu a:active {
color: rgb(185 54 61);
text-decoration: underline;
}
#menu button {
color: #bebebe;
border: solid 2px rgb(185 54 61);
border-radius: 5px;
background-color: rgba(0,0,0,.7);
padding: 3px 15px;
outline: none;
cursor: pointer;
transition: background-color 250ms;
}
#menu button:hover {
background-color: rgba(185, 54, 61, .6);
color: #fff;
}
#menu input[type=checkbox] {
margin-right: 5px;
cursor: pointer;
}
#menu label {
cursor: pointer;
}
body.play #menu {
display: flex;
}
#helpMessage {
opacity: 0;
position: fixed;
left: 0;
right: 0;
bottom: 0;
text-align: center;
margin: 0 0 10px 0;
transition: opacity 250ms;
}
body.play #helpMessage.show {
opacity: 1;
}
#grid {
display: none;
flex-direction: column;
flex: 1;
height: 90vmin;
width: 90vmin;
margin: auto;
}
body.play #grid {
display: block;
}
#grid .row {
display: flex;
flex-direction: row;
}
#grid .col {
display: flex;
width: 7.7vmin;
height: 7.4vmin;
margin: 0;
border-radius: 1px;
transition: box-shadow 100ms ease-in-out;
}
#grid .cell {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
color: white;
z-index: 1000;
}
#grid .row:first-child {
margin-top: 21.2vmin;
}
#grid .button {
margin-left: 11vmin;
margin-right: 1.7vmin;
}
#grid .button.switch .cell {
margin: 1.7vmin 1.3vmin .9vmin 1.3vmin;
border-radius: .25vmin;
transition: box-shadow 250ms, background-color 250ms;
}
#grid .button.selected .cell {
box-shadow: 0 0 1vmin 0.5vmin rgb(255 80 80);
background-color: rgba(255,180,180,.5);
}
#grid .button, #grid .chamber {
cursor: pointer;
position: relative;
}
#grid .chamber .southWall {
visibility: hidden;
width: 100%;
position: absolute;
bottom: -1vmin;
left: 0;
height: 1.9vmin;
display: block;
z-index: 10;
background-image: url('../images/southWall.png');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
#grid .chamber .eastWall {
visibility: hidden;
height: 100%;
position: absolute;
top: 0;
right: -1.1vmin;
width: 2vmin;
display: block;
z-index: 10;
background-image: url('../images/eastWall.png');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
#grid .chamber .secretRoomOne, #grid .chamber .secretRoomTwo, #grid .chamber .treasureRoom {
position: absolute;
left: 1vmin;
top: 1.3vmin;
right: 1.1vmin;
bottom: 1.2vmin;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
#grid .chamber .secretRoomOne {
background-image: url('../images/warriorOneMarker.png');
}
#grid .chamber .secretRoomTwo {
background-image: url('../images/warriorTwoMarker.png');
}
#grid .chamber .treasureRoom {
background-image: url('../images/treasureMarker.png');
}
#grid .chamber .warriorOne, #grid .chamber .warriorTwo, #grid .chamber .dragon, #grid .chamber .treasure {
background-position: bottom center;
background-repeat: no-repeat;
position: absolute;
left: 0;
right: 0;
bottom: 1vmin;
}
#grid .chamber .warriorOne, #grid .chamber .warriorTwo {
display: none;
height: 11vmin;
}
.gameStarted #grid .chamber .warriorOne, .gameStarted #grid .chamber .warriorTwo {
display: block;
}
#grid .chamber .warriorOne {
background-size: auto 90%;
background-image: url("../images/warriorOne.png");
}
#grid .chamber .warriorTwo {
background-size: auto 100%;
background-image: url("../images/warriorTwo.png");
}
#grid .chamber .dragon {
background-size: auto 100%;
height: 14vmin;
background-image: url("../images/dragon.png");
}
#grid .chamber .treasure {
background-size: auto 100%;
height: 10vmin;
background-image: url("../images/treasure.png");
}
#grid .chamber .treasure.withWarrior {
transform: translate(1.7vmin, 2.9vmin) scale(.5);
}
body.debug #container.layoutDebug #grid .col.button, body.debug #container.layoutDebug #grid .col.chamber {
background-color: rgba(0,0,0,.4);
}
body.debug #grid .cell.northWallDebug {
border-top: solid .5vmin #eee;
}
body.debug #grid .cell.eastWallDebug {
border-right: solid .5vmin #eee;
}
body.debug #grid .cell.southWallDebug {
border-bottom: solid .5vmin #eee;
}
body.debug #grid .cell.westWallDebug {
border-left: solid .5vmin #eee;
}
body.debug #grid .cell.northDoorDebug {
border-top: dotted .5vmin #eee;
}
body.debug #grid .cell.eastDoorDebug {
border-right: dotted .5vmin #eee;
}
body.debug #grid .cell.southDoorDebug {
border-bottom: dotted .5vmin #eee;
}
body.debug #grid .cell.westDoorDebug {
border-left: dotted .5vmin #eee;
}
body.debug #grid .cell.northOpenDebug {
border-top: dotted .5vmin rgba(255,255,255,.25);
}
body.debug #grid .cell.eastOpenDebug {
border-right: dotted .5vmin rgba(255,255,255,.25);
}
body.debug #grid .cell.southOpenDebug {
border-bottom: dotted .5vmin rgba(255,255,255,.25);
}
body.debug #grid .cell.westOpenDebug {
border-left: dotted .5vmin rgba(255,255,255,.25);
}
body.debug #grid .chamber.traveledDebug .cell {
background-color: rgba(0,0,255,.4);
}
body.debug #grid .chamber.travelingDebug .cell {
background-color: rgba(255,0,0,.4);
}
body.debug #grid .chamber.treasureOptionDebug .cell {
background-color: rgba(255,215,0,.4);
}
body.debug #grid .chamber.treasureDebug .cell {
background-color: rgba(255,215,0, .6);
}
body.debug #grid .chamber .dragon {
display: block;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+101
View File
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://www.googletagmanager.com" />
<link rel="stylesheet" href="./css/main.css" />
<script type="application/javascript" src="./js/main.js" defer></script>
<link rel="canonical" href="https://dndlabyrinth.com/" />
<link rel="icon" type="image/jpg" href="./icons/icon128x128.jpg" sizes="128x128">
<link rel="icon" type="image/jpg" href="./icons/icon152x152.jpg" sizes="152x152">
<link rel="icon" type="image/jpg" href="./icons/icon167x167.jpg" sizes="167×167">
<link rel="icon" type="image/jpg" href="./icons/icon180x180.jpg" sizes="180×180">
<link rel="icon" type="image/jpg" href="./icons/icon192x192.jpg" sizes="192×192">
<link rel="icon" type="image/jpg" href="./icons/icon196x196.jpg" sizes="196×196">
<meta name="description" content="This game is a simulation of the Mattel Electronics&trade; Dungeons and Dragons&trade; Computer Labyrinth Game"/>
<meta property="og:url" content="https://dndlabyrinth.com/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Dungeons &amp; Dragons&trade; Computer Labyrinth Game Simulator" />
<meta property="og:description" content="This game is a simulation of the Mattel Electronics&trade; Dungeons and Dragons&trade; Computer Labyrinth Game" />
<meta property="og:image" content="https://dndlabyrinth.com/images/featuredImage.jpg" />
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebApplication",
"name": "Dungeons & Dragons&trade; Computer Labyrinth Game Simulator",
"url": "https://dndlabyrinth.com",
"description": "This game is a simulation of the Mattel Electronics&trade; Dungeons and Dragons&trade; Computer Labyrinth Game",
"applicationCategory": "Game",
"author":{
"@type": "Person",
"name": "Bob Whitley"
},
"genre": "Board Game",
"browserRequirements": "ECMAScript version 6 and HTML5",
"softwareVersion": "1.1.0",
"operatingSystem": "All"
}
</script>
<title>Dungeons &amp; Dragons&trade; Computer Labyrinth Game Simulator</title>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-B171BVLV8D"></script>
<script>
if (window.location && window.location.hostname == "dndlabyrinth.com") {
window.gaEnabled = true;
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-B171BVLV8D');
}
</script>
</head>
<body>
<main>
<div id="intro">
<div id="header">
<h1>Dungeons &amp; Dragons&trade;<br/>Computer Labyrinth Game<br/>Simulator</h1>
</div>
<p>
This game is a simulation of the Dungeons and Dragons&trade; Computer Labyrinth Game&trade;
made by <a rel="noopener" href="https://www.mattel.com/en-us" target="_blank">Mattel Electronics</a>&trade; released in 1980.
</p>
<p>
I owned this game back in 1981 when I was 11 years old and only recently rediscovered it so I
thought it would be a fun project to recreate it on the internet for others to enjoy.
</p>
<p>
To play the game simply press the play button below. If you are new to the game I recommend reading the
original <a href="./assets/gameManual.pdf" target="_blank">game manual</a> to get familiar with the game play.
The game relies on sound queues for play so be sure to have your speakers turned on or enable the in-game
help messages.
</p>
<p>
Enjoy!
</p>
<p class="subtext">
Images of the game, the manual, game pieces, artwork and any audio are copyright of <a rel="noopener" href="https://www.mattel.com/en-us" target="_blank">Mattel</a>&trade;
<br/>
Dungeons and Dragons&trade; is copyright of <a rel="noopener" href="https://company.wizards.com/" target="_blank">Wizards of the Coast</a>&trade;
</p>
</div>
<div id="container">
<div id="start"><div class="text">Click to Play</div></div>
<div id="board"></div>
<div id="menu">
<div id="menuLeft">
<a id="exit">&laquo; Exit</a>
</div>
<div id="menuCenter">
<button id="reset">Reset</button>
</div>
<div id="menuRight">
<input id="help" type="checkbox" value="help" /> <label for="help">Show Help</label>
</div>
</div>
<div id="helpMessage"></div>
</div>
</main>
</body>
</html>
File diff suppressed because it is too large. Load diff