4D tic-tac-toe (real)

This commit is contained in:
osmarks 2024-01-30 16:46:38 +00:00
parent f43a8aa951
commit b0c118bb65
40 changed files with 272 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -21,7 +21,7 @@ const metricDisplayInfo = {
commentsPosted: { name: "Comments posted", units: "comment" },
greatestInfipage: { name: "Largest infipage visited" },
heavpootLocations: { name: "Heavpoot's Game states", units: "state" },
heavpootDeaths: { name: "Heavpoot's Game deaths", units: "death" }
heavpootDeaths: { name: "Heavpoot's Game deaths", units: "death" },
}
for (const opponent of ["ai1", "ai2"]) {
@ -30,6 +30,10 @@ for (const opponent of ["ai1", "ai2"]) {
}
}
for (const result of ["Wins", "Losses", "Draws"]) {
metricDisplayInfo[`ttt4${result}`] = { name: `${result} in 4D Tic-Tac-Toe`, units: "game" }
}
const displayMetric = metric => {
let name = metric[0]
let value = metric[1]

View File

@ -360,6 +360,8 @@ slug: tictactoe
function render() {
var html = ""
for (var l = 0; l < size; l++) {
if (l == 2) html += `</div>`
if (l == 0 || l == 2) html += `<div class="ctr">`
html += '<div class="layer">'
for (var r = 0; r < size; r++) {
html += '<div class="row">'
@ -373,6 +375,7 @@ slug: tictactoe
}
html += '</div>'
}
if (l == 3) html += `</div>`
html += '</div>'
}
screen.innerHTML = html

View File

@ -0,0 +1,2 @@
.layer{margin:1em;border:1px solid #666;display:inline-block}.cell{display:flex;flex-direction:column}.slot{width:2rem;height:2rem;display:inline-block;border:1px solid #aaa;font-size:.5em}.slot-1{background:#00f}.slot-2{background:red}.board,.row{display:flex}.highlight{width:50%;height:50%;top:25%;left:25%;position:relative}.abspos-indicator{height:100%;background-size:cover}
/*# sourceMappingURL=app.css.map */

View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../app.css"],
"sourcesContent": [".layer {\n margin: 1em;\n border: 1px solid #666;\n display: inline-block;\n}\n.cell {\n display: flex;\n flex-direction: column;\n}\n.slot {\n width: 2rem;\n height: 2rem;\n display: inline-block;\n border: 1px solid #aaa;\n font-size: 0.5em;\n}\n.slot-1 {\n background: blue;\n}\n.slot-2 {\n background: red;\n}\n.board {\n display: flex;\n}\n.row {\n display: flex;\n}\n.highlight {\n width: 50%;\n height: 50%;\n top: 25%;\n left: 25%;\n position: relative;\n}\n.abspos-indicator {\n height: 100%;\n background-size: cover;\n}"],
"mappings": "AAAA,CAAC,MAAD,OACY,IACR,OAAQ,IAAI,MAAM,KAClB,QAAS,YACb,CACA,CAAC,KACG,QAAS,KACT,eAAgB,MACpB,CACA,CAAC,KACG,MAAO,KACP,OAAQ,KACR,QAAS,aACT,OAAQ,IAAI,MAAM,KAClB,UAAW,IACf,CACA,CAAC,OACG,WAAY,IAChB,CACA,CAAC,OACG,WAAY,GAChB,CACA,CAAC,MAGD,CAAC,IAFG,QAAS,IACb,CAIA,CAAC,UACG,MAAO,IACP,OAAQ,IACR,IAAK,IACL,KAAM,IACN,SAAU,QACd,CACA,CAAC,iBACG,OAAQ,KACR,gBAAiB,KACrB",
"names": []
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect x="25%" width="12.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="75%" width="12.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 232 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect x="25%" width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="75%" width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="50%" width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="37.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="50%" width="37.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 224 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect y="25%" height="12.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="75%" height="12.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 232 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect y="25%" height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="75%" height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="50%" height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect height="37.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="50%" height="37.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 224 B

2
experiments/tictactoe4d/dist/app.css vendored Normal file
View File

@ -0,0 +1,2 @@
.layer{margin:1em;border:1px solid #666;display:inline-block}.cell{display:flex;flex-direction:column}.slot{width:2rem;height:2rem;display:inline-block;border:1px solid #aaa;font-size:.5em}.slot-1{background:#00f}.slot-2{background:red}.board,.row{display:flex}.highlight{width:50%;height:50%;top:25%;left:25%;position:relative}.abspos-indicator{height:100%;background-size:cover}
/*# sourceMappingURL=app.css.map */

View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../app.css"],
"sourcesContent": [".layer {\n margin: 1em;\n border: 1px solid #666;\n display: inline-block;\n}\n.cell {\n display: flex;\n flex-direction: column;\n}\n.slot {\n width: 2rem;\n height: 2rem;\n display: inline-block;\n border: 1px solid #aaa;\n font-size: 0.5em;\n}\n.slot-1 {\n background: blue;\n}\n.slot-2 {\n background: red;\n}\n.board {\n display: flex;\n}\n.row {\n display: flex;\n}\n.highlight {\n width: 50%;\n height: 50%;\n top: 25%;\n left: 25%;\n position: relative;\n}\n.abspos-indicator {\n height: 100%;\n background-size: cover;\n}"],
"mappings": "AAAA,CAAC,MAAD,OACY,IACR,OAAQ,IAAI,MAAM,KAClB,QAAS,YACb,CACA,CAAC,KACG,QAAS,KACT,eAAgB,MACpB,CACA,CAAC,KACG,MAAO,KACP,OAAQ,KACR,QAAS,aACT,OAAQ,IAAI,MAAM,KAClB,UAAW,IACf,CACA,CAAC,OACG,WAAY,IAChB,CACA,CAAC,OACG,WAAY,GAChB,CACA,CAAC,MAGD,CAAC,IAFG,QAAS,IACb,CAIA,CAAC,UACG,MAAO,IACP,OAAQ,IACR,IAAK,IACL,KAAM,IACN,SAAU,QACd,CACA,CAAC,iBACG,OAAQ,KACR,gBAAiB,KACrB",
"names": []
}

3
experiments/tictactoe4d/dist/app.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect x="25%" width="12.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="75%" width="12.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 232 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect x="25%" width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="75%" width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="50%" width="25%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="37.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
<rect x="50%" width="37.5%" height="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 224 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect y="25%" height="12.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="75%" height="12.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 232 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect y="25%" height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="75%" height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="50%" height="25%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect height="37.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
<rect y="50%" height="37.5%" width="100%" fill="rgb(0 0 0 / 10%)" />
</svg>

After

Width:  |  Height:  |  Size: 224 B

12
experiments/tictactoe4d/dist/index.html vendored Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>4D Tic-Tac-Toe</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<div id="app"></div>
<script src="app.js"></script>
</body>
</html>

Binary file not shown.

View File

@ -0,0 +1,41 @@
/* app.css */
.layer {
margin: 1em;
border: 1px solid #666;
display: inline-block;
}
.cell {
display: flex;
flex-direction: column;
}
.slot {
width: 2rem;
height: 2rem;
display: inline-block;
border: 1px solid #aaa;
font-size: 0.5em;
}
.slot-1 {
background: blue;
}
.slot-2 {
background: red;
}
.board {
display: flex;
}
.row {
display: flex;
}
.highlight {
width: 50%;
height: 50%;
top: 25%;
left: 25%;
position: relative;
}
.abspos-indicator {
height: 100%;
background-size: cover;
}
/*# sourceMappingURL=webworker_glue.css.map */

View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../app.css"],
"sourcesContent": [".layer {\n margin: 1em;\n border: 1px solid #666;\n display: inline-block;\n}\n.cell {\n display: flex;\n flex-direction: column;\n}\n.slot {\n width: 2rem;\n height: 2rem;\n display: inline-block;\n border: 1px solid #aaa;\n font-size: 0.5em;\n}\n.slot-1 {\n background: blue;\n}\n.slot-2 {\n background: red;\n}\n.board {\n display: flex;\n}\n.row {\n display: flex;\n}\n.highlight {\n width: 50%;\n height: 50%;\n top: 25%;\n left: 25%;\n position: relative;\n}\n.abspos-indicator {\n height: 100%;\n background-size: cover;\n}"],
"mappings": ";AAAA,CAAC;AACG,UAAQ;AACR,UAAQ,IAAI,MAAM;AAClB,WAAS;AACb;AACA,CAAC;AACG,WAAS;AACT,kBAAgB;AACpB;AACA,CAAC;AACG,SAAO;AACP,UAAQ;AACR,WAAS;AACT,UAAQ,IAAI,MAAM;AAClB,aAAW;AACf;AACA,CAAC;AACG,cAAY;AAChB;AACA,CAAC;AACG,cAAY;AAChB;AACA,CAAC;AACG,WAAS;AACb;AACA,CAAC;AACG,WAAS;AACb;AACA,CAAC;AACG,SAAO;AACP,UAAQ;AACR,OAAK;AACL,QAAM;AACN,YAAU;AACd;AACA,CAAC;AACG,UAAQ;AACR,mBAAiB;AACrB;",
"names": []
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
---
title: Tic-Tac-Toe (4⁴)
description: More dimensions. More confusion. Somewhat worse performance. 4D Tic-Tac-Toe.
slug: tictactoe4
---
<link rel="stylesheet" href="app.css">
<div id="app"></div>
<script src="app.js"></script>

Binary file not shown.

View File

@ -0,0 +1,41 @@
/* app.css */
.layer {
margin: 1em;
border: 1px solid #666;
display: inline-block;
}
.cell {
display: flex;
flex-direction: column;
}
.slot {
width: 2rem;
height: 2rem;
display: inline-block;
border: 1px solid #aaa;
font-size: 0.5em;
}
.slot-1 {
background: blue;
}
.slot-2 {
background: red;
}
.board {
display: flex;
}
.row {
display: flex;
}
.highlight {
width: 50%;
height: 50%;
top: 25%;
left: 25%;
position: relative;
}
.abspos-indicator {
height: 100%;
background-size: cover;
}
/*# sourceMappingURL=webworker_glue.css.map */

View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../app.css"],
"sourcesContent": [".layer {\n margin: 1em;\n border: 1px solid #666;\n display: inline-block;\n}\n.cell {\n display: flex;\n flex-direction: column;\n}\n.slot {\n width: 2rem;\n height: 2rem;\n display: inline-block;\n border: 1px solid #aaa;\n font-size: 0.5em;\n}\n.slot-1 {\n background: blue;\n}\n.slot-2 {\n background: red;\n}\n.board {\n display: flex;\n}\n.row {\n display: flex;\n}\n.highlight {\n width: 50%;\n height: 50%;\n top: 25%;\n left: 25%;\n position: relative;\n}\n.abspos-indicator {\n height: 100%;\n background-size: cover;\n}"],
"mappings": ";AAAA,CAAC;AACG,UAAQ;AACR,UAAQ,IAAI,MAAM;AAClB,WAAS;AACb;AACA,CAAC;AACG,WAAS;AACT,kBAAgB;AACpB;AACA,CAAC;AACG,SAAO;AACP,UAAQ;AACR,WAAS;AACT,UAAQ,IAAI,MAAM;AAClB,aAAW;AACf;AACA,CAAC;AACG,cAAY;AAChB;AACA,CAAC;AACG,cAAY;AAChB;AACA,CAAC;AACG,WAAS;AACb;AACA,CAAC;AACG,WAAS;AACb;AACA,CAAC;AACG,SAAO;AACP,UAAQ;AACR,OAAK;AACL,QAAM;AACN,YAAU;AACd;AACA,CAAC;AACG,UAAQ;AACR,mBAAiB;AACrB;",
"names": []
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -151,6 +151,12 @@ window.points = (async () => {
conditions: "Recurse to a stack depth of 100 or more on RPNCalc v4",
description: "For using RPNCalcV4 as it is meant to be used - highly, highly recursively.",
points: 18.324
},
ttt4Win: {
title: "Shape Rotator",
conditions: "Win 4D Tic-Tac-Toe",
description: "You won a game of 4D Tic-Tac-Toe against our highly advanced artificial intelligence, showing your utter comprehension of 4D space.",
points: 37.9
}
}
@ -407,21 +413,21 @@ if (sidenotes && footnotes) {
const notes = []
// read off sidenotes to place
for (const item of footnoteItems) {
const itemRect = item.getBoundingClientRect()
const link = article.querySelector(`#${item.id.replace(/^fn/, "fnref")}`)
const linkRect = link.getBoundingClientRect()
item.style.position = "absolute"
item.style.left = getComputedStyle(sidenotes).paddingLeft
item.style.marginBottom = item.style.marginTop = `${BORDER / 2}px`
item.style.paddingBottom = item.style.paddingTop = `${BORDER / 2}px`
const itemRect = item.getBoundingClientRect()
notes.push({
item,
height: itemRect.height + BORDER,
height: itemRect.height,
target: linkRect.top - snRect.top
})
}
// preliminary placement: place in valid regions going down
for (const note of notes) {
const index = inclusions.findLastIndex(inc => (inc.start + note.height) < note.target)
const index = Math.max(inclusions.findLastIndex(inc => (inc.start + note.height) < note.target), 0)
const next = inclusions.slice(index)
.findIndex(inc => (sum(inc.contents.map(x => x.height)) + note.height) < (inc.end - inc.start))
inclusions[index + next].contents.push(note)
@ -506,6 +512,22 @@ if (sidenotes && footnotes) {
window.relayout = relayout
}
const fixDetailsSummary = () => {
const el = document.getElementById(window.location.hash.slice(1))
var parent = el
if (!el) return
while (parent.parentElement) {
if (parent.nodeName === "DETAILS") {
parent.setAttribute("open", true)
}
parent = parent.parentElement
}
el.scrollIntoView()
}
window.addEventListener("hashchange", fixDetailsSummary)
fixDetailsSummary()
const customStyle = localStorage.getItem("user-stylesheet")
let customStyleEl = null
if (customStyle) {