Files
Landon Curt Noll a1c86c8a7a add original C links to entry navigation bars
The navigation bar for a winning entry now has a "_Original C_" link
(between the ✅ and the Inventory on the right hand side) so that one
may easily view the original C code that was submitted for IOCCC judging.

Ran `make www timestamp` to perform the above.
2025-08-10 12:46:23 -07:00

731 lines
28 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!-- START: two lines up starts content from: inc/top.default.html -->
<!-- END: this line ends content from: inc/top.default.html -->
<!-- START: this line starts content from: inc/head.default.html -->
<head>
<link rel="stylesheet" href="../../ioccc.css">
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>2019/diels-grabsch2 - Most self-aware</title>
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
<meta name="description" content="2019 IOCCC entry diels-grabsch2 - Most self-aware">
<meta name="keywords" content="IOCCC, 2019, IOCCC 2019, IOCCC entry, diels-grabsch2, Most self-aware">
</head>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<!-- END: this line ends content from: inc/head.default.html -->
<!-- -->
<!-- This web page was formed via the tool: bin/readme2index.sh -->
<!-- The content of main section of this web page came from: 2019/diels-grabsch2/README.md -->
<!-- -->
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<!-- !!! Do not modify this web page, instead modify the file: 2019/diels-grabsch2/README.md !!! -->
<!-- !!! Do not modify this web page, instead modify the file: 2019/diels-grabsch2/README.md !!! -->
<!-- !!! Do not modify this web page, instead modify the file: 2019/diels-grabsch2/README.md !!! -->
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
<!-- START: this line starts content from: inc/body.default.html -->
<body>
<!-- END: this line ends content from: inc/body.default.html -->
<!-- START: this line starts content from: inc/topbar.default.html -->
<div class="theader">
<nav class="topbar">
<div class="container">
<div class="logo">
<a href="../../index.html" class="logo-link">
IOCCC
</a>
</div>
<div class="topbar-items">
<div class="item">
<span class="item-header">
Entries
</span>
<div class="sub-item">
<div class="outfit-font">
<a href="../../years.html" class="sub-item-link">
Winning entries
</a>
</div>
<div class="outfit-font">
<a href="../../authors.html" class="sub-item-link">
Winning authors
</a>
</div>
<div class="outfit-font">
<a href="../../location.html" class="sub-item-link">
Location of authors
</a>
</div>
<div class="outfit-font">
<a href="../../bugs.html" class="sub-item-link">
Bugs and (mis)features
</a>
</div>
<div class="outfit-font">
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
Fixing entries
</a>
</div>
<div class="outfit-font">
<a href="../../faq.html#fix_author" class="sub-item-link">
Updating author info
</a>
</div>
</div>
</div>
<div class="item">
<span class="item-header">
Status
</span>
<div class="sub-item">
<div class="outfit-font">
<a href="../../news.html" class="sub-item-link">
News
</a>
</div>
<div class="outfit-font">
<a href="../../status.html" class="sub-item-link">
Contest status
</a>
</div>
<div class="outfit-font">
<a href="../../next/rules.html" class="sub-item-link">
IOCCC rules
</a>
</div>
<div class="outfit-font">
<a href="../../next/guidelines.html" class="sub-item-link">
IOCCC guidelines
</a>
</div>
<div class="outfit-font">
<a href="../../markdown.html" class="sub-item-link">
Markdown guidelines
</a>
</div>
<div class="outfit-font">
<a href="../../SECURITY.html" class="sub-item-link">
Security policy
</a>
</div>
</div>
</div>
<div class="item">
<span class="item-header">
FAQ
</span>
<div class="sub-item">
<div class="outfit-font">
<a href="../../faq.html" class="sub-item-link">
Frequently asked questions
</a>
</div>
<div class="outfit-font">
<a href="../../quick-start.html#enter" class="sub-item-link">
Enter the IOCCC
</a>
</div>
<div class="outfit-font">
<a href="../../faq.html#compiling" class="sub-item-link">
Compiling entries
</a>
</div>
<div class="outfit-font">
<a href="../../faq.html#running_entries" class="sub-item-link">
Running entries
</a>
</div>
<div class="outfit-font">
<a href="../../faq.html#help" class="sub-item-link">
How to help
</a>
</div>
</div>
</div>
<div class="item">
<span class="item-header">
About
</span>
<div class="sub-item">
<div class="outfit-font">
<a href="../../index.html" class="sub-item-link">
Home page
</a>
</div>
<div class="outfit-font">
<a href="../../social.html" class="sub-item-link">
IOCCC social media
</a>
</div>
<div class="outfit-font">
<a href="../../about.html" class="sub-item-link">
About the IOCCC
</a>
</div>
<div class="outfit-font">
<a href="../../judges.html" class="sub-item-link">
The judges
</a>
</div>
<div class="outfit-font">
<a href="../../thanks-for-help.html" class="sub-item-link">
Thanks for the help
</a>
</div>
<div class="outfit-font">
<a href="../../contact.html" class="sub-item-link">
Contact us
</a>
</div>
</div>
</div>
</div>
</div>
</nav>
<div class="header-mobile-menu">
<noscript>
<a href="../../nojs-menu.html" class="topbar-js-label">
Please Enable JavaScript
</a>
</noscript>
<button id="header-open-menu-button" class="topbar-mobile-menu">
<img
src="../../png/hamburger-icon-open.png"
alt="hamburger style menu icon - open state"
width=48
height=48>
</button>
<button id="header-close-menu-button" class="hide-content">
<img
src="../../png/hamburger-icon-closed.png"
alt="hamburger style menu icon - closed state"
width=48
height=48>
</button>
<div id="mobile-menu-panel" class="hide-content">
<div class="mobile-menu-container">
<div class="mobile-menu-wrapper">
<div class="mobile-menu-item">
Entries
</div>
<div class="mobile-submenu-wrapper">
<a class="mobile-submenu-item" href="../../years.html">
Winning entries
</a>
<a class="mobile-submenu-item" href="../../authors.html">
Winning authors
</a>
<a class="mobile-submenu-item" href="../../location.html">
Location of authors
</a>
<a class="mobile-submenu-item" href="../../bugs.html">
Bugs and (mis)features
</a>
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
Fixing entries
</a>
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
Updating author info
</a>
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
Thanks for the help
</a>
</div>
</div>
<div class="mobile-menu-wrapper">
<div class="mobile-menu-item">
Status
</div>
<div class="mobile-submenu-wrapper">
<a class="mobile-submenu-item" href="../../news.html">
News
</a>
<a class="mobile-submenu-item" href="../../status.html">
Contest status
</a>
<a class="mobile-submenu-item" href="../../next/rules.html">
IOCCC rules
</a>
<a class="mobile-submenu-item" href="../../next/guidelines.html">
IOCCC guidelines
</a>
<a class="mobile-submenu-item" href="../../markdown.html">
Markdown guidelines
</a>
<a class="mobile-submenu-item" href="../../SECURITY.html">
Security policy
</a>
</div>
</div>
<div class="mobile-menu-wrapper">
<div class="mobile-menu-item">
FAQ
</div>
<div class="mobile-submenu-wrapper">
<a class="mobile-submenu-item" href="../../faq.html">
Frequently asked questions
</a>
<a class="mobile-submenu-item" href="../../quick-start.html#enter">
Enter the IOCCC
</a>
<a class="mobile-submenu-item" href="../../faq.html#compiling">
Compiling entries
</a>
<a class="mobile-submenu-item" href="../../faq.html#running_entries">
Running entries
</a>
<a class="mobile-submenu-item" href="../../faq.html#help">
How to help
</a>
</div>
</div>
<div class="mobile-menu-wrapper">
<div class="mobile-menu-item">
About
</div>
<div class="mobile-submenu-wrapper">
<a class="mobile-submenu-item" href="../../index.html">
Home page
</a>
<a class="mobile-submenu-item" href="../../social.html">
IOCCC social media
</a>
<a class="mobile-submenu-item" href="../../about.html">
About the IOCCC
</a>
<a class="mobile-submenu-item" href="../../judges.html">
The judges
</a>
<a class="mobile-submenu-item" href="../../contact.html">
Contact us
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
headerOpenMenuButton.addEventListener("click", () => {
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
headerOpenMenuButton.classList.add("hide-content");
headerCloseMenuButton.classList.remove("hide-content");
headerCloseMenuButton.classList.add("topbar-mobile-menu");
mobileMenuPanel.classList.remove("hide-content");
mobileMenuPanel.classList.add("topbar-mobile-panel");
});
headerCloseMenuButton.addEventListener("click", () => {
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
headerCloseMenuButton.classList.add("hide-content");
mobileMenuPanel.classList.add("hide-content");
mobileMenuPanel.classList.remove("topbar-mobile-panel");
headerOpenMenuButton.classList.add("topbar-mobile-menu");
headerOpenMenuButton.classList.remove("hide-content");
});
</script>
<!-- END: this line ends content from: inc/topbar.default.html -->
<!-- START: this line starts content from: inc/header.default.html -->
<div class="header">
<a href="../../2011/zucker/index.html">
<img src="../../png/ioccc.png"
alt="IOCCC image by Matt Zucker"
width=300
height=110>
</a>
<h1>The International Obfuscated C Code Contest</h1>
<h2>2019/diels-grabsch2 - Most self-aware</h2>
<h3>Self hashing</h3>
</div>
<!-- END: this line ends content from: inc/header.default.html -->
<!-- START: this line starts content from: inc/navbar.mid.html -->
<div class="navbar">
<a class="Left" href="../diels-grabsch1/index.html">&larr; 2019/diels-grabsch1</a>
<a class="Left" href="../index.html">&uarr; 2019 &uarr;</a>
<a class="Left" href="../dogon/index.html">2019/dogon &rarr;</a>
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/prog.c">C code</a>
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/Makefile">Makefile</a>
<a class="Right" href="#inventory">Inventory</a>
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/prog.orig.c">Original C</a>
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2019%2Fdiels-grabsch2%2Findex.html">&#x2713;</a>
</div>
<!-- END: this line ends content from: inc/navbar.mid.html -->
<!-- START: this line starts content from: inc/before-content.default.html -->
<div class="content" id="content">
<!-- END: this line ends content from: inc/before-content.default.html -->
<!-- START: this line starts content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-author.sh -->
<h2 id="author">Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Volker_Diels-Grabsch">Volker Diels-Grabsch</a><br>
Location: <a href="../../location.html#DE">DE</a> - <em>Federal Republic of Germany</em> (<em>Germany</em>)</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
<!-- END: this line ends content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- BEFORE: 1st line of markdown file: 2019/diels-grabsch2/README.md -->
<h2 id="to-build">To build:</h2>
<pre><code> make</code></pre>
<h2 id="to-use">To use:</h2>
<pre><code> ./prog</code></pre>
<h2 id="try">Try:</h2>
<pre><code> ./try.sh</code></pre>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>Before running this one, stay calm. Chill out, have a cup of tea. Is this bad?</p>
<p>To understand what is going on here, please check if you are dreaming, or are you dreaming
that you are dreaming? Or is it, wake up from the simulation?</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="almost-a-hash-collision">Almost a hash collision:</h3>
<p>This program prints its own SHA-512 hash. To verify, run:</p>
<pre><code> $ sha512sum prog.c; ./prog
43bd0c4381a5078d2850fca9ae5e0647596bcc03cd67d8d973ad02ff35c316c728e7b347ca70abe6c74e745e63646cc7643cb0cffcd3d9a969cbf31a7ce5bf68 prog.c
43bd0c4381a5078d2850fca9ae5e0647596bcc03cd67d8d973ad02ff35c316c728e7b347ca70abe6c74e745e63646cc7643cb0cffcd3d9a969cbf31a7ce5bf68</code></pre>
<p>It started as a complicated “hello world” program that prints some random hex
digits instead of “hello world”. Then, the digits were adjusted until the
resulting program matched its own SHA-512 hash, via brute force through all
2^512 possibilities. Just kidding.</p>
<p>This wasn’t brute force, but involved quite some math, using a variant of Jane
Doe’s algorithm for generating SHA-512 collisions efficiently. If you still
don’t believe me, you are right.</p>
<p>No crypto was broken in the making of this program!</p>
<p>The trick is that under the hood, this program is a quine! That is, it is aware
of its own source code in string representation. But instead of printing that
string (its own source), its SHA-512 hash is computed and printed. So two major
steps were needed to obfuscate this program:</p>
<ol type="1">
<li>Hide the quine.</li>
<li>Hide the SHA-512 computation.</li>
</ol>
<p>Note that both steps were achieved mostly algorithmically. The code
is otherwise as short and as clean as possible. The implementation is
portable C99 code for 32-bit and 64-bit systems that compiles without
any warnings on current GCC and Clang versions even with <code>-Wextra -Weverything</code>. The program is composed of mostly pure functions, and
the <code>#define</code>s are only used to shorten redundant parts of the code,
they are not meant to obfuscate much. Having that out of the way, how
are step 1 and step 2 achieved then?</p>
<p>Regarding step 1, note that the large string literal</p>
<pre><code> &quot;`x{bh}ndbq...&quot;</code></pre>
<p>in the last line doesn’t look like C code. Moreover, it is too short
to contain even a compressed representation of all preceding and
subsequent code. Instead, the preceding code including the <code>"</code>
character has already been run through the SHA-512 computation by an
external script. The internal state of the SHA-512 computation at
that point has been extracted and encoded into the string. This works
because the preceding code is exactly 1280 bytes, which is a multiple
of 1024 bits, the block size of SHA-512. The program itself then just
continues the SHA-512 computation from that point, adding the last
1024-bit block, finalizing the hash and printing it. The last block
is taken directly from the string literal at runtime, plus the
subsequent code which consists of just <code>"</code>, <code>;</code> and <code>\n</code>. Those 3
characters are short enough to be hidden in … well, let’s leave this
as an exercise for the reader.</p>
<p>To summarize, the main trick here is to move the string constant to
the end, so the preceding code can be pre-calculated and the subsequent
code is short enough to be hidden anywhere.</p>
<p>Regarding step 2, almost all macros, functions and variables have
meaningless single-letter names. Moreover, the SHA-512 computation is
reduced to the special case of adding just one block and immediately
finalizing it, where the total size is known in advance.</p>
<p>But this is not enough! For SHA-512 we need 8 initial hash values and 80 round
constants, which are very characteristic. If any of them appeared in the
source, a quick web search (e.g. for <code>0x428a2f98d728ae22</code>) would tell the reader
immediately what’s going on. Because of the pre-computation, the 8 initial hash
values are not needed, but the 80 round constants are.</p>
<p>It is almost impossible to hide those 640 bytes in the source.
Luckily, the round constants where not chosen by fair dice rolls.
They are the fractional parts of certain irrational numbers, namely,
the cube roots of the first 80 primes. So the round constants are
calculated at runtime, which makes the program shorter and adds
another layer of obfuscation.</p>
<p>While this sounds like just iterating primes and executing <code>pow(3)</code>, this
turned out to be harder than expected. If we were computing SHA-256,
it would have been as simple as that, because the round constants
would have been 32-bit values. However, SHA-512 needs the cube roots
at 64-bit precision, while <code>double</code> has only 53-bit mantissa precision.</p>
<p>Using higher-precision floating point is no option here, because the
program is meant to be portable C99. And implementing arbitrary-precision
arithmetic would have been overkill and would have increased the program size
dramatically.</p>
<p>Instead, the program just multiplies. That is, it computes cubes
instead of cube roots. It steps through cube root candidates via
bisection, and calculates their cubes until those match the given
prime. Thus, we don’t need floating point and can use 64-bit integers
instead. But that still doesn’t solve the problem as it poses the
following new challenges:</p>
<ul>
<li>Challenge 1: We can multiply at most two 32-bit numbers at once.</li>
<li>Challenge 2: We need to calculate with at least 67-bit precision.</li>
<li>Challenge 3: We need to truncate the cube root result.</li>
</ul>
<p>The reason for challenge 1 is that in portable C99, the result must
fit into the same data type. To multiply two 64-bit integers we would
need a 128-bit integer for the result. So we can at most multiply two
32-bit integers to get the 64-bit product at full precision. While
GCC and Clang both support 128-bit arithmetics, that isn’t standard
and wouldn’t have been portable C99.</p>
<p>The reason for challenge 2 is that cube root of the 80th prime is
around 7, so we need to compute with 3 bits for the integral part and
64 bits for the fractional part.</p>
<p>The reason for challenge 3 is that the cube of a 67-bit number is
<code>3*67=201</code> bits, but fortunately we only need to check if it is close
enough to the actual prime. It won’t be exactly <code>409.0000...</code>
anyway, but must be accurate enough to distinguish the correct cube
root from its neighbours, e.g. the same number with the 64th
fractional digit increased.</p>
<p>The solution here is to split the 67-bit input into 3 integers of
24-bit each. Those are cubed using the multiplication formulas
numbers with 3 “digits” of base <code>2^24</code> each. During that calculation,
at most two values are multiplied at once, and the accuracy of
intermediate values is reduced using right-shifts as far as allowable
for the computation. Finding working right-shift values was mostly
trial-and-error, producing correct results for the first 80 primes,
but not much more. Moreover, for some terms it was possible to leave
them out entirely, especially higher-order terms of the last digits.
Luckily, in the end, all intermediate results did fit into 64-bit
integer addition and multiplication, but that was not obvious at the
beginning.</p>
<p>That’s it.</p>
<p>Well, I could continue with details about the encoding of the internal
state values into the string, how to avoid escaping issues, how to
find short notations for various loops, how to get rid of <code>if()</code>, where
the final <code>"\";\n"</code> is stored, how to eliminate intermediate values and
arrays by reordering of operations, and so on. But those were all
minor issues compared to the challenges described above. What’s
documented here is all you need to know to write your own version of
that program.</p>
<p>I’d like to finish with an open problem:</p>
<p>Is it possible for the cubing and bisection to be implemented with
just two parts instead of three? That would simplify the formulas a
lot. For example, one could split the 67-value into two 34-bit parts,
but whenever one multiplies two of them, one needs to right-shift one
of them by at least 4 bits, or both by 2. Or, one splits the 67 bits
asymmetrically? I was unable to make it work with 2 parts, but that
doesn’t have to mean anything.</p>
<!--
Copyright © 1984-2024 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/
-->
<!-- AFTER: last line of markdown file: 2019/diels-grabsch2/README.md -->
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<div id="inventory">
<h1 id="inventory-for-2019diels-grabsch2">Inventory for 2019/diels-grabsch2</h1>
</div>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/prog.c">prog.c</a> - entry source code</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/prog.orig.c">prog.orig.c</a> - original source code</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/try.sh">try.sh</a> - script to try entry</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="2019_diels-grabsch2.tar.bz2">2019_diels-grabsch2.tar.bz2</a> - download entry tarball</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/README.md">README.md</a> - markdown source for this web page</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/.entry.json">.entry.json</a> - entry summary and manifest in JSON</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/winner/blob/master/2019/diels-grabsch2/.path">.path</a> - directory path from top level directory</li>
<li><a href="index.html">index.html</a> - this web page</li>
</ul>
<hr style="width:10%;text-align:left;margin-left:0">
<h4>
Jump to: <a href="#">top</a>
</h4>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
<!-- END: this line ends content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content from: inc/after-content.default.html -->
</div>
<!-- END: this line ends content from: inc/after-content.default.html -->
<!-- START: this line starts content from: inc/footer.inventory.html -->
<!--
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/
-->
<div class="footer">
<div id="copyright"><h3>Copyright &copy; 1984-2025 by Landon Curt Noll:
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
target="_blank"
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
<p>
This work is <b>licensed by Landon Curt Noll</b> under
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
target="_blank"
rel="license noopener noreferrer"
style="display:inline-block;">CC BY-SA 4.0</a></b>.
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
src="../../png/cc.png"
alt="cc inside circle symbol">
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
src="../../png/by.png"
alt="person inside circle symbol">
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
src="../../png/sa.png"
alt="arrow looping back on itself inside circle symbol"><br>
You should <b>carefully review</b> the
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
target="_blank"
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
before using the licensed material.<br>
You may wish to review the
<b><a href="../../license.html"
target="_blank"
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
of <b>CC BY-SA 4.0</b>.<br>
</p>
</div>
<div id="coda"><h3>Coda</h3>
<p>
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2019%2Fdiels-grabsch2%2Findex.html" rel="nofollow">Nu HTML check this web page</a><br>
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a> <a href="#inventory">Jump to Inventory</a><br>
</p>
</div>
</div>
<!-- END: this line ends content from: inc/footer.inventory.html -->
<!-- START: this line starts content from: inc/bottom.default.html -->
</body>
</html>
<!-- END: this line ends content from: inc/bottom.default.html -->