DOOM Using Regular Expressions

Regular expressions (regexes) are an amazingly powerful way to perform operations on collections of e.g. text. Regexss can also be considered to be a programming language, even a Turing complete one. Ergo it’s perfectly acceptable to thus design a way to use regexes to run and play a game of DOOM, as [Artem Lytkin] recently did.

The GitHub project page can be found here, containing the Python-based code that allows the demonstration to run, as well as the other components, including the C runtime and the 96.6 MB text string that defines a CPU’s registers, RAM, a framebuffer, the DOOM engine compiled to this custom CPU’s instruction set and the WAD file for the game itself.

The C-based driver applies the fixed, ordered list of find-and-replace rules to this string, which after more than ten-thousand of such substitutions later results in a single frame of the game. At about 80,000 substitutions per second on the given test system, that gets you to a sort-of playable framerate, even.

Naturally, the practical value of playing DOOM like this is pretty low, but as a demonstration of why regexes are awesome it’s hard to beat.

20 thoughts on “DOOM Using Regular Expressions”

  1. There’s nothing awesome about regex’s.
    In years of software engineering our group always said there were 3 evils of computer science:

    LDAP
    Certificates
    Regex’s

    Why?
    It is next to impossible to know what the coder intended scope of the regx to be.
    The side effects and unintended security vulnerabilities are enormous. Let alone figuring how to change it without implementing weeks consuming unit tests.

    1. I would really like an article that explores the most widely loathed technologies in software engineering. Perhaps a survey to collect a list then a poll for voting, then a deep dive on each of the top 10 into why they were so bad, along with a bit of devil’s advocate that attempts to provide some redemption.

    2. What I learned from using regex a lot is that while I’m smart enough to create 1 large regex to solve problems it’s often easier to use 1 or more simple regex strings and basic string operations to get the result you want. If you want a regex string to do everything all at once they can get very complex, hard to test and hard to modify.
      Ultimately a regex string is a finite state machine design.

    3. You forgot MISRA. If what they intended was a dumbed down C, they should have created a new programming language.

    4. i don’t understand… i mean, it really depends what you’re using it for… i mostly use regex with perl and grep in one-off hacks like to parse / compare test case outputs or to collate a dataset i just downloaded. i find it super handy because there’s so little effort to use it, and it doesn’t matter if it is too complicated to debug because it just has to work the one time. there’s usually no security implication because i just use it on the one dataset i already downloaded (and perhaps already sanitized).

      i also sometimes use it for like cgi-bin or crontab that does download new stuff every day…in principle it could be a security risk, but it’s no different from any other programming…just don’t lose touch with where the string came from! in that case, i heavily prefer simple regex to complicated regex, because i might need to maintain it. ugh, i can’t imagine what hackaday will do to this string but like “if ($input =~ /^[a-z]+$/)” or “$input =~ s/[^a-z]/./g/” are pretty bulletproof. It’s easy to sanitize input with regex, you just shouldn’t forget to do it!

      the biggest tension with regex imo is that there’s actually a pretty small range of situations where it makes sense to use something that complicated (as opposed to just like regular C “if (!strcmp(…))”) but that is also simple enough that regex is amenable to it. like, for parsing a language with nesting concepts, regex is almost completely unsuited. to parse XML or C/JSON-style expressions in perl, i usually use regex to write a lexer and then regular recursive descent to parse the lexed tokens.

      so i guess i’m asking, what kind of twisted things are you using regex for where it becomes a problem? or maybe i’m admonishing, “if it hurts when you hit your head with a hammer, DON’T hit your head with a hammer!” :) but hammers are still very useful

    5. And to that I will give a counterargument through examples.

      The PDF is specification is complete enough that you can write a virtual machine that will run inside a (compliant) PDF reader.

      That doesn’t make the PDF format bad.
      It doesn’t detract from it’s use as a print document formatting tool.

      If there is something “evil” about it, the evil comes from how it was used.

      The same can be said about HTML5 or WASM or any other “just be lazy and run the whole damn thing in the browser” approach.

      I don’t always agree with the Linux Ethos of “simple tools for 1 job” but sometimes that really is the answer on the back end.

    6. LDAP, Certificates, and Regex? Cute.

      You forgot the fourth evil: DNS.

      The only one capable of breaking all three while insisting everything is working as intended.

  2. The pedant in me can’t resist pointing out that regular expressions are very much NOT Turing complete. If what you’re using is Turing complete then it’s not a regular expression.

    1. Thank God. For a moment, I was worried that the fully functional computer running DOOM might actually be computing something.
      Apparently, if you build a CPU out of regex substitutions, implement memory, execute instructions, and run an entire game, it still doesn’t count because a finite automaton can’t do that by itself.
      Fascinating. By that logic, transistors aren’t Turing-complete either, so I guess computers don’t exist.

  3. Regexss can also be considered to be a programming language, even a Turing complete one
    [EXTREMELY LOUD INCORRECT BUZZER NOISE]
    regex is a chomsky type 3 grammar. which means it is not turing complete

  4. Computer science has spent 70 years developing abstractions to make programming easier.
    Then someone implements an entire CPU using regex substitutions, runs DOOM on it, and reminds us that every abstraction is just an elaborate way of avoiding the inevitable: moving bits around until something catches fire.
    The real achievement isn’t running DOOM with regex.
    It’s managing to create a 96 MB string that’s somehow more maintainable than the average enterprise Java application.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.