Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

CTFFuck2

Welcome to the abyss. To its esolang wiki.

Table of Contents

Table of Technical Contents


What is this?

This is CTFFuck2. It's a surgical reconstruction of the language's soul, built to weaponize deterministic chaos against anyone foolish enough to try writing a working program.

The well-known digital esolangs already turned programming into a nightmare. CTFFuck2 pushes that nightmare into a new dimension: global state coupling via a shared ring buffer and path-dependent operand resolution.

There is no randomness. No encryption. Just a handful of rules that burnt your brains up.


The Core Mechanic: Global Shared Ring Buffer

All instructions' temporary arguments live in a single fix_queue with a global head_pointer. Every time any instruction calls stack.push(value), the head advances by 1 and the value is written at the previous head position. When an instruction later needs its saved argument, it reads via stack.at(offset) — where offset is a compile-time constant indicating how many steps back in the buffer the value should be.

Because the head keeps moving, the same offset might point to completely different memory depending on when the read occurs. This means:

  • You cannot statically determine what operand an instruction will receive.
  • You must integrate every push that happened between the write and the read.
  • Even instructions that "finished" their pairing leave residues that can be accidentally consumed by a mistimed at().

Instruction Behavior

OpcodeNameStack lengthNotes
0read1First call pushes address, second call reads memory.
1add1First call pushes address, second call adds to memory.
2set0Zeros a memory cell.
3push0Pushes a value directly into the shared buffer (no indirection).
4print0Prints the character at the given memory address.
5swap1Two-step pairing to swap memory contents.
6grow1Transposon. Generates new instructions and injects them.
7inp0Reads one character from stdin into a memory cell.
8jmpm1Conditional jump based on flags.
9revf0Flips zero flag, sign flag or control flag.

The stack length indicates how many values the instruction will push into the global buffer during a single complete operation. Those values will be read back later using at(offset) where the offset equals the instruction’s starting offset plus its stack depth minus 1… unless the head has been moved by other instructions.


The push instruction: instant injection

push no longer has its own stack. It writes directly to the global buffer at the current head and advances the head. The next instruction that reads from the buffer will consume that value if its at(offset) happens to land on it — but only if the offset and head align correctly. This makes push an art form of aligning the head position so the injected value reaches the right consumer.


The grow instruction: transposon

grow still takes three parameters (spindle, method, argument) and can produce new digits which then get executed as if they were part of the original program. Methods 0–4 compute a new digit from the current memory state; method 5 swaps function pointers in the opcode table.

Every grow outcome is a deterministic consequence of the current state and the instruction’s arguments. This makes the language fully deterministic — yet whose behavior remains fundamentally unpredictable without executing it.


Building and Running

Build from source code

CPP Version

If you want to build from source code, you need a C++17 compiler (for std::filesystem and lambdas) and a Unix-like environment (the terminal raw mode uses termios.h).

ASM Version

Run the build.sh given in the directory asm-version/ or its command

Run the binary

CPP Version

If you just want to execute from the binary

./ctffuck2 -f /path/to/your/file # execute from file

or

./ctffuck2 -r "8754"# execute immediately

ASM Version

To be small, the asm version does NOT support flagged parameters, it will only execute on one positional parameter:

./ctffuck2 /path/to/your/file

Flags (For CPP Version):

  • -f, --file : Path to the program file (a string of digits, other characters ignored).
  • -d--debug : (Currently a no-op; debugging is done by staring into the void.)
  • -i, --input : The input for the program

Credits

The CTFFuck2 was created for whom equations are the only language worth speaking.

Go stare into the abyss. The abyss will not stare back — it will just make you solve for its head pointer.

About

This is a esolang that uses only ten characters, to form a incredible complex computer language

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages