A Digital Computer has the wrong name to begin with. John von Neumann, at the very beginning (late forties), called it the All-Purpose Machine, and that was the right name, but it got mislaid somewhere. A digital computer is a device which can be programmed to move information [, they] can also count, and do arithmetic. But this numerical activity of computers has been vastly overemphasized. For it is their ability to vary and combine programs, test the outside world and modify it (through input and output), and handle the general diddling of vast quantities of information [...] that makes it, in some very important sense, the ultimate machine.
A computer language is usually a set of artificial words [...] which a programmer may combine by some set of rules into a long spell (a program). This spell is then given in some way to another program in the computer, the “language processor”, which turns the relatively few instructions in the computer language into the many ittybitty instructions needed by the computer itself. If the spell is properly cast, the system does what the programmer wants [...]
In the book, the programming language used to create the 10print composition is BASIC, this language was incredibly popular for many years (including among artists, especially in the 1980s) but is no longer considered a very modern language. Today, there are loads of different programming languages out there, they all basically do the same thing: allow you to "cast spells" (as Ted Nelson put it) or write programs that get the computer to do what you want it to do. While all programming languages share the same fundamental principles, some are better suited for certain tasks over others. Often this has to do with the context you're writing your program in/for. In our case, we're writing code to create generative art online, and so we'll be using the Web's native programming language: JavaScript.
For a more thorough review of the core programming concepts discussed in the link above, consider reading the first few chapters from Marijn Haverbeke's book Eloquent JavaScript (4th edition 2024) as well as the Mozilla Developer Network's JavaScript language overview.
After reviewing the JavaScript notes above, we should now be familiar with all the core components of our craft: variables and data types, functions, loops and conditional statements. Apart from these fundamental principles of programming, there is only one more thing we need in order to recreate 10print in JavaScript: Randomness. Assuming you've already done the reading and reviewed the notes on randomness, it's now time to unlock it's potential using JavaScript's built-in random number function Math.random()
xxxxxxxxxx
1
<script>
2
3
log(typeofMath)
4
5
</script>
...
There's a variable built into the JavaScript language called Math. The "type" of this variable is object which is the only datatype not discussed in the Core Concepts examples linked above. It's not a simple data-type like numbers or strings, instead it's a data structure, a way of collecting all the previously mentioned types of data into a single "object".
The coding concepts we've covered so far are built into the JavaScript programming language. Like most programming languages, you can run JavaScript code by "compiling" it in a terminal (most commonly with node.js that's the JIT, or "just in time" compiler used to create all sorts of web servers and modern applications). But other JavaScript compilers (or interpreters) are actually built into many common applications, allowing you to use JavaScript to "script" or control these applications in numerous ways. For example, JavaScript can be used in many different contexts, you write JavaScript in Adobe software like Photoshop or Illustrator to automate different processes which would otherwise need to done manually by a user. You can write JavaScript in the Microsoft Office suite to automate processes there as well. You can also write JavaScript within other graphical programming environments like Max to extend it's capabilities.
JavaScript on the Web
The most common application we use JavaScript to control is the app you're using to read this page right now, the web browser (of which there are many iterations of, Chrome, Firefox, etc). As described in the introduction section of the JavaScript Core Concepts, inorder to write JavaScript in a Web page (which is traditionally writtin in HTML) we need a special HTML element, the <script> element. We can use the script element to include JavaScript on the web a couple of different ways, either by placing our JavaScript code in it's own file and then importing it using this element's "src" property, like this <script src="my-file.js"></script> or we can simply write our JavaScript between a pair of opening and closing scrip tags (which is what we'll be doing for this 10print project).
In addition to a script element, we'll also be including a couple of other elements in our 10print project's template. The first is a link element. This element is used to import other resources into our HTML page, most commonly CSS code, which is what we'll be using it for. By default text on a webpage is usually black on a white background. But in order to simulate the look of an old-school Commodore 64 computer (which is light text on a blue background), as well as handle a couple of other styling inconsistencies across browsers, we'll be importing simple CSS file I wrote. Lastly, we'll also need a body element, the element which will contain all the text characters we'll be algorithmically generating. All together our HTML template looks like this:
When we use JavaScript inside a particular application we gain access to that application's "APIs", or Application Programming Interface. In this context, an API is just a set of coding tools (functions, classes, etc) built into the browser (or any given application) which we can access and use via JavaScript.
Later in this course we'll start using JavaScript "frameworks" or "libraries" which will abstract some of these APIs making them easier to use, but for now we'll interact with some of these APIs directly, by making use of the following objects:
window, the window object gives us access to different parts of our browser window, both data about it, but also functions to control parts of it. Below are just some of the properties (internal variables) and methods (internatl functions) of the window object.
window.innerHeight this will tell us how tall the inner portion of our window is in pixels, everytime we change the size of our browser window this value gets automatically updated. We can also get the window.outerHeight which includes the address bar, bookmarks, menu items or other aspects of the browser window (but this is usually less useful for our generative art pieces)
window.innerWidth this tells us the width of our window in pixels, like the previous property, this also updates anytime the browser is resized. There is also window.outerWidth
window.scrollTo(x, y) in our 10print variations, it is very likely that we'll add enough content to our page that it'll go off screen, this means the viewer will need to scroll the page to see anything "below the fold". We could, however, control the scroll bar programatically using the window object's scrollTo method. This method takes two arguments, first the position of the horizontal scroll bar (in pixels) and second the position you want to place the vertical scroll bar at.
document the document object gives us access to every part of our HTML document, meaning any/all HTML elements (the code which structures an HTML page) and their CSS values (the code that changes the look/presentation of a web page). This is part of one of the most fundamental web API's called the DOM (or document object model). Later we'll use libraries which will make it easier for us to work with this API, but for now we'll use just a few parts of it directly.
document.body this is how we access our web page's "body" element, the main element which contains everything we can visually see on our page. There's lots we can do to the body (and any other element using the DOM API) but we'll focus on just a few.
document.body.innerText this property allows us to access the text currently within the body element, as well as modify it. To change the body's text you can reassign this property new value as you would any other variable: document.body.innerText = 'some new text' we can also append text (meaning add to the text that's currently there, rather than replacing it) by using the += operator instead of =.
document.body.style if you're familiar with CSS, you should know that you can modify any of the body's CSS values using the "style" property, for example document.body.style.color = 'red' will change all of the body's text color to red. Note: if you want to modify a CSS value that normally contains a dash like "font-family" you must write this property name in camel case like this: document.body.style.fontFamily = 'monospace'
Of course this is a "static" version of 10print, we can "refresh" (or re-run) the example above by clicking the "refresh" button below it to create another randomly generated iteration, but these will always be static. To recrate that character by character animated feel of the original Commodore 64 version we need to introduce another set of JavaScript functions which will unlock another key aspect of generative art: animation.
As mentioned in the Web API section above, as we add more content to our page in an animation loop, eventually the text will start to go off screen, the user will need to scroll the page to see the bottom of the text. To automate this scrolling we can use the window.scrollTo(), passing in 0 as its first argument (aassuming we don't have a horizontal scroll bar) and passing in document.body.offsetHeight as it's second argument. The body's offsetHeight is a property which updates every time the body's size changes (say for example because we've added more text into it) to match the current height of the body element in pixels. If we pass this value as the second argument to our scrollTo method then it essentially scrolls to the bottom of the page. Here's a netnet example with auto-scrolling.
10 PRINT in your own style
Our meditation on 10print, our first assignment, is as much about the code we write as it is the visual output it generates. We want to use this as a chance not only to practice the core concepts of programming (variables, functions, loops and conditional statements) and of generative art (randomness and animation), but also to start developing our own coding style, the way we express our ideas in code. Even with this simple example, 10print, there are a number of different ways we could write this in JavaScript each with it's own style reflecting different values. We might value clarity, in which case we might write it very verbosely, with lots of comments and clearly named variables. Or, we might value efficiency, choosing to keep our code compact, minimizing the number of operations we require of the computer. Or, we might value poetics, choosing to write code in a style which is as much about form as it is function, like this piece Ode to a Chain of Blocks by artist Kaspar Ravel.
Here's a simple algorithm which will create a static version of the 10print pattern (with 1000 characters). Let's explore other variations on this same algorithm to learn a bit about how JavaScript can be written a number of different ways to express the same idea.
The examples above are each a more compact version of the one that came before it. We start with a version that values clarity over efficiency and we end with a version that prioritizes tightly written efficient code. But there are countless of other values we might prioritize. For example check out this incredibly tiny, creative and demoscene inspired implementation by Mathieu 'p01' Henri.
As another example, maybe we want to create a version of 10 print in JavaScript that resembles as much as possible the original version written in BASIC. In the BASIC version, rather than using string values for the characters, a function called CHR$() is used, there is a similar function in JavaScript called String.fromCharCode() which we can use to create our own "CHR$" function.
The original CHR$ function would take a numerical value representing the character you want, in the case of the Commodore 64 and PET, these were encoded in PETSCII. Most computers today use ASCII and/or Unicode which not only contains a much larger character set, but is also a different mapping of numerical values to corresponding characters. Which means rather than starting with the value 205.5 and randomly choosing to round that up or down (the values 205 and 206 representing the slashes in PETSCII) we'd use the values 9585 and 9586, which are those longer box diagonal characters in Unicode.
more 10 PRINT variations
Below are a couple of examples of creative remixes of the original 10print algorithm, but instead of running on a Commodore 64, these are running on the Commodore PET (an older model from 1977), which displays its text in a green color on a black background. You can replace the link element from the original template with this one:
if you'd like to go with a more PET color scheme. Keep in mind, if you're familiar with CSS you could always write your own CSS code between a pair of style elements in place of this link element (the CSS code we're importing isn't all that complicated).
The video above demonstrates a very simple "video game" based on the 10print algorithm, written in BASIC (same as the original 10print). The video below is an absolutely beautiful "demo" which features a reference to 10print towards the beginning of the piece. The video below is a recording of a demo by shiru8bit you can check out his own YouTube channel here. Unlike Vera Molnár and the other artists we discussed in the intro to Generative Art and Randomness notes, shiru8bit is not a part of the "art world" proper, but instead practices generative art in an "outsider" computer art sub-culture known as the demoscene which we'll discuss later this quarter.
Keep in mind, everything we've just discussed has been primarily focused on recreating 10print, meaning we've limited the characters generated to the ╱ (Unicode value 9585) and ╲ (Unicode value 9586), but we could have used other characters and we could have used other logic to probabalistically determine which to render. There are loads of creative possabilities in terms of the compositions we can algorithmically create simply by drawing text characters onto the screen. For more inspiration check out the work by contemporary generative artists like Julian Hespenheide and Andreas Gysin.