96 lines
5.1 KiB
Markdown
96 lines
5.1 KiB
Markdown
---
|
||
created_at: '2016-07-24T14:03:11.000Z'
|
||
title: Purely Functional Retrogames (2008)
|
||
url: http://prog21.dadgum.com/23.html
|
||
author: adgasf
|
||
points: 87
|
||
story_text:
|
||
comment_text:
|
||
num_comments: 29
|
||
story_id:
|
||
story_title:
|
||
story_url:
|
||
parent_id:
|
||
created_at_i: 1469368991
|
||
_tags:
|
||
- story
|
||
- author_adgasf
|
||
- story_12153325
|
||
objectID: '12153325'
|
||
|
||
---
|
||
[Source](http://prog21.dadgum.com/23.html "Permalink to Purely Functional Retrogames, Part 1")
|
||
|
||
# Purely Functional Retrogames, Part 1
|
||
|
||
[programming in the
|
||
twenty-first century][1]
|
||
|
||
It's not about technology for its own sake. It's about being able to implement your ideas.
|
||
|
||
# Purely Functional Retrogames, Part 1
|
||
|
||
When I started looking into functional languages in 1998, I had just come off a series of projects writing video games for underpowered hardware: Super Nintendo, SEGA Saturn, early PowerPC-based Macintoshes without any graphics acceleration. My benchmark for usefulness was "Can a programming language be used to write complex, performance intensive video games?"
|
||
|
||
After working through basic tutorials, and coming to grips with the lack of destructive updates, I started thinking about how to write trivial games, like Pac-Man or Defender, in a purely functional manner. Then I realized that it wasn't performance that was the issue, it was much more fundamental.
|
||
|
||
_I had no idea how to structure the most trivial of games without using destructive updates._
|
||
|
||
Pac-Man is dead simple in any language that fits the same general model as C. There are a bunch of globals representing the position of Pac-Man, the score, the level, and so on. Ghost information is stored in a short array of structures. Then there's an array representing the maze, where each element is either a piece of the maze or a dot. If Pac-Man eats a dot, the maze array is updated. If Pac-Man hits a blue ghost, that ghost's structure is updated to reflect a new state. There were dozens and dozens of Pac-Man clones in the early 1980s, including tiny versions that you could type in from a magazine.
|
||
|
||
In a purely functional language, none of this works. If Pac-Man eats a dot, the maze can't be directly updated. If Pac-Man hits a blue ghost, there's no way to directly change the state of the ghost. How could this possibly work?
|
||
|
||
That was a long time ago, and I've spent enough time with functional languages to have figured out how to implement non-trivial, interactive applications like video games. My plan is to cover this information in a short series of entries. I'm sticking with 8-bit retrogames because they're simple and everyone knows what Pac-Man looks like. I don't want to use abstract examples involving hypothetical game designs. I'm also sticking with purely functional programming language features, because that's the challenge. I know that ML has references and that processes in Erlang can be used to mimic objects, but if you go down that road you might as well be using C.
|
||
|
||
The one exception to "purely functional" is that I don't care about trying to make I/O fit a functional model. In a game, there are three I/O needs: input from the user, a way to render graphics on the screen, and a real-time clock. Fortunately, these only matter at the very highest level outer loop, one that looks like:
|
||
|
||
|
||
repeat forever {
|
||
get user input
|
||
process one frame
|
||
draw everything on the screen
|
||
wait until a frame's worth of time has elapsed
|
||
}
|
||
|
||
"Process one frame" is the interesting part. It takes the current game state and user input as parameters and returns a new game state. Then that game state can be used for the "draw everything" step. "Draw everything" can also be purely functional, returning an abstract list of sprites and coordinates, a list that can be passed directly to a lower level, and inherently impure, function that talks to the graphics hardware.
|
||
|
||
An open question is "Is being purely functional, even excepting I/O, worthwhile?" Or is it, as was suggested to me via email earlier this year, the equivalent of writing a novel without using the letter 'e'?
|
||
|
||
[Part 2][2]
|
||
|
||
[permalink][3] _April 12, 2008_
|
||
|
||
# previously
|
||
|
||
* [My Road to Erlang][4]
|
||
* [Slumming with BASIC Programmers][5]
|
||
* [In Praise of Non-Alphanumeric Identifiers][6]
|
||
* [Five Memorable Books About Programming][7]
|
||
* [Back to the Basics of Functional Programming][8]
|
||
|
||
# [archives][9]
|
||
|
||
[**twitter][10]** / [**mail][11]**
|
||
|
||
I'm James Hague, a [recovering programmer][12] who has been designing video games since the 1980s. [Programming Without Being Obsessed With Programming][13] and [Organizational Skills Beat Algorithmic Wizardry][14] are good starting points. For the older stuff, try the [2012 Retrospective][15].
|
||
|
||
Where are [the comments][16]?
|
||
|
||
[1]: http://prog21.dadgum.com/
|
||
[2]: http://prog21.dadgum.com/24.html
|
||
[3]: http://prog21.dadgum.com/23.html
|
||
[4]: 22.html
|
||
[5]: 21.html
|
||
[6]: 20.html
|
||
[7]: 19.html
|
||
[8]: 18.html
|
||
[9]: http://prog21.dadgum.com/archives.html
|
||
[10]: https://twitter.com/dadgumjames
|
||
[11]: mailto:james.hague%40gmail.com
|
||
[12]: http://prog21.dadgum.com/56.html
|
||
[13]: http://prog21.dadgum.com/195.html
|
||
[14]: http://prog21.dadgum.com/177.html
|
||
[15]: http://prog21.dadgum.com/162.html
|
||
[16]: http://prog21.dadgum.com/57.html
|
||
|