1
0

Ported articles

This commit is contained in:
Jon Michael Aanes 2024-03-10 14:53:47 +01:00
parent 6d0a0cae98
commit f58a7cbf95
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
5 changed files with 503 additions and 0 deletions

View File

@ -0,0 +1,46 @@
# Doki Doki Densha Sekai
![A train has arrived at a station, as colorful cube-people
hustle.](/website/images/dokidoki.png)
**Nordic Game Jam 2016 People's Choice Awards finalist**
A relaxing exploration of a metro system. Put on a pair of headphones
and immerse yourself in a world of trains and cube people.
Made in cooperation with _[Sketchwhale](http://takunomi.space)_
and _[Astrid Sonne](https://soundcloud.com/a_sonne)_
Download on [itch.io](https://jmaa.itch.io/doki-doki-densha-sekai).
Original description:
> **Doki Doki Densha Sekai** is a first step to see when a world begins to
> form in the mind of the player. Try and visit all the unique stations
> such as complex __Inu-shibuya__, the religious center
> __O-biiru-no-mizu__ and curiously circular __Manko-mae__. If you miss
> either your ride or stop, don't worry about it. Relax and listen to
> the easy-going music while you wait. It might be a while.
>
> Was made for **Nordic Game Jam 2016**, by the following people:
>
> - [Sketchwhale](http://takunomi.space) made the design and the art.
> - [Astrid Sonne](https://soundcloud.com/a_sonne) created the music you'll hear throughout.
> - [JMAA](/) was stressed out coupling everything together.
## March 2019 Update
The game have been updated to fix several issues, and some minor
features have been implemented.
## September 2019 Update
The game has been updated once again, with following patch notes:
- The fonts have been reworked, removing some visual artifacts.
- An introductory main menu have been added.
- Xbox controller support has been added. Other controllers may
work, but as I only possess a Xbox controller, I am unable to
confirm.

View File

@ -0,0 +1,91 @@
# Tigersay
## The dOvs Course ##
This last semester I've been following my university's course on
writing a compiler from scratch. The course uses the classic
[Modern Compiler Implementation in
ML](https://www.cs.princeton.edu/%7Eappel/modern/ml/), and thus our
input language is something called **Tiger**, a toy language designed
specifically for the book. The joke goes that Tiger is one of the
least used programming languages, but one of the most supported. It is
also weird. It's like if **C** and [Standard
ML](https://en.wikipedia.org/wiki/Standard_ML) had a deformed baby:
Mutually inductive data types and functions? Sure! Primitives for both
functional and imperative coding styles? Great idea! Type inference
for variables, but not for functions. Perfect! A way to determine the
size of arrays at runtime? No, absolutely not!
![A small piece of Tiger code, demonstrating an implementation of a
linked list.](/website/images/tiger-example.png)
The reason for these weird idiosyncrasies is obvious: nobody is
supposed to write actual programs in Tiger. The features of
Tiger are designed to illustrate how to implement them, not
necessarily to form a coherent whole.
That said, some of the features work together to allow a strange
elegance in the way some programs can be written. Recursive functions
and structure types allow one to express linked lists and maps using
relatively little code. See [the example
code](https://gitfub.space/Jmaa/tigersay/src/branch/master/tiger-linked-list.tig)
above, for an implementation of a linked list, and a function for finding the sum of
the list, using a recursive helper function. I could just as easily
have implemented it using an imperative style.
<!-- TODO: Include link to tests. -->
While following the course, my group used a testing framework,
containing many programs similar in style to the above code sniplet,
ensuring our compiler's compliance with the language. These
tests were small, and rarely tested more than a few features at once.
The question "Is our compiler actually capable of translating a _real_
program?" arose, and this lead me down the road of actually writing a
"real" program in Tiger, using its weird feature set.
## Tigersay ##
<!--start-->
![A badly drawn tiger explains its own existence: "Once upon a time,
there was a programming language named Tiger, and nobody used it. Then
some stupid student made a clone of cowsay, and that is how I was
born"](/website/images/tigersay-example.png)
**Tigersay** is an implementation of the classic Perl program
[Cowsay](https://en.wikipedia.org/wiki/Cowsay), written in the Tiger
programming language, a toy language originating from the [Modern
Compiler Implementation in
ML/C/Java](https://www.cs.princeton.edu/%7Eappel/modern/ml/) series of
books.
It does not come compiled, nor does it come with a **Tiger** compiler.
The only way to experience the wonder that is **Tigersay** is to use
your own **Tiger** compiler. (Or find one on the internet, but that's
cheating.)
<!--end-->
The standard version of Tiger is limited in its ability to interact
with the command-line, and as a result, so is Tigersay. The only way
to interact with Tigersay is to pipe the desired text into Tigersay:
```bash
echo "Hello World" | tigersay
```
Unfortunately this also means Tigersay only supports a single face,
the default tiger one, due to having no support for command-line
arguments.
Tigersay responds to certain strings in silly ways, the most useful
ones being _help_ and _version_. Additionally it interfaces nicely
with [fortune](https://en.wikipedia.org/wiki/Fortune_(Unix\)).
![The badly drawn tiger exclaim: "I never made a mistake in my life.
I thought I did once, but I was wrong. -- Lucy Van
Pelt"](/website/images/tigersay-fortune.png)
If you'd like to play around with Tigersay yourself, you can find the source
code in the [Gitfub repository](https://gitfub.space/Jmaa/tigersay)

View File

@ -0,0 +1,105 @@
# Infernal Interpreter
## The dComArk Course ##
My first semester of University (summer 2015) I had a course named
**Computer Architecture** commonly shorted to **dComArk**. It was a
standard course about the low level construction of modern computers.
It followed [Tanenbaum](http://www.cs.vu.nl/~ast/)'s classic
[Structured Computer
Organization](http://www.mypearsonstore.com/bookstore/structured-computer-organization-9780132916523).
The course itself was known for its [idiosyncratic
lecturer](https://twitter.com/nielsolofbouvin), and for being hard as
hell. Topics included registers, the stack, assembly code,
micro-code, and the architecture of processors in general.
Jumping directly from just having learnt Java, as a first programming
language, to suddenly having to understand and write low-level
programming languages such as
[IJVM](https://en.wikipedia.org/wiki/IJVM) and [X86-64
assembly](https://en.wikipedia.org/wiki/X86-64), was tough, and many
of my fellow students dropped out because of it.
My favorite assignment was the one where we extended IJVM
with a new op-code. You see, some processors are programmable, in
their own [highly restricted programming
language](https://en.wikipedia.org/wiki/MIC-1). Changing something you
think is set in stone - like the set of op-codes a processor has -
changes the way you see the world.
But this article is neither about IJVM, nor about micro-code. It's
about the course's fifth and final assignment. For this assignment we
were to write a recursive [fibonnaci
function](https://rosettacode.org/wiki/Fibonacci_sequence) in x86-64,
and then describe how it worked, with visualizations of the registers
and stack at every instruction.
![Example of the recursive Fibonacci function in x86, with
comments.](/website/images/infernal-interpreter-example.png)
[A friend of mine](https://christoffer.space/) spent an entire evening
on this assignment carefully drawing the [registers and stack into
Excel](/website/images/infernal-interpreter_christoffer-stack.pdf).
I decided I'd rather spend an evening programming, than messing about
with Excel, so I began writing a program that could generate code for
embedding into LaTeX. The program needed to emulate just enough
X86-64 to run the function, and no more.
## The Infernal Interpreter ##
<!--start-->
![Example of Infernal Interpreter output. Columns describe the
movement of data when executing x86
op-codes.](/website/images/infernal-interpreter-output-ascii.png)
**Infernal Interpreter** is an emulator and visualizer of a subset of
the AMD x86-64 ABI, using the GAS syntax. You give it a bunch of
symbolic machine code, after which it produces a visualization of the
running code, either to the terminal, or as a LaTeX file with Tikz.
It's old, written in Python 2, and for an incredibly specific purpose,
but I enjoy going back and looking at the output.
<!--end-->
There is something at once uncomfortable and fascinating about looking
at old code. Thoughts of "How could I ever write code this bad?" and
"Damned, I've gotten a lot better since then". While writing this
article I wanted some images that fits the style of my website, so I
added a `ascii` painting mode, that shows the trace in the terminal.
This was non-trivial, given the existing structures, which were
clearly designed to be as obscure as possible. Along the way the
frontend was updated to be more UNIX-like. The backend is a nightmare,
and has been kept without major changes.
If you'd like to take at look at it as well, you can find an [an
example of the tikz output
here](/website/images/infernal-interpreter_tikz-example.pdf).
Alternatively you can [download the program
itself](/website/images/infernal-interpreter_source-1.0.0.zip), or
[view the official Git
repository](https://gitfub.space/Jmaa/infernal-interpreter).
**Infernal Interpreter** requires **Python 2**, and will crash on
anything remotely complicated. Notably: it does not model the heap.
The source-code is available under the BEERWARE license, so you are
free to modify it as you like.
![Example of Infernal Interpreter output, with the Tikz painter.
Columns describe the movement of data when executing x86
op-codes.](/website/images/infernal-interpreter-output-tikz.png)
The program includes two example files in the `examples` folder, both
of which were part of my assignment, and has been included unaltered.
You can run them with a command like this:
./infernal
-i=examples/fibonnaci_recursive.S
--rdi=3
The `--rdi=3` argument is important, because it sets the `%rdi`
register to `3`, and thus tells the program to compute the 3rd
Fibonacci number. This writes ascii directly to the terminal. To
produce Tikz, simply change the painter: `--painter tikz`. The full
options can be found by running `./infernal --help`

View File

@ -0,0 +1,175 @@
# Nijousatsujikenriron (AKA "The Elevator Game")
![Adrift on the seas of change; a world of our own making.](/website/images/nijousatsujikenriron-mock-up.png)
**Nijousatsujikenriron** is a murder-mystery dating-sim set in an
elevator. As Detective Monaghan, you just had the worst, and probably
last, day of your career. As you enter the elevator, you feel things
are not going to get better. Can you solve the mystery? Can you find
yourself? Can you move on?
Made in cooperation with _[Sketchwhale](http://takunomi.space)_
and _[Mikko "Mishicu" Aaltio](https://twitter.com/mishicumusic)_
Download on [itch.io](https://jmaa.itch.io/nijousatsujikenriron).
## Introduction ##
Last weekend, 13-15th April 2018, I participated in [Nordic Game
Jam](https://nordicgamejam.org/), a yearly gamejam set in Copenhagen.
I did not enjoy the trip at all, but was very satisfied with the
resulting game.
Most of this post is a rant about trains, the jam, implementation
details, etc.
## Transport Purgatory ##
I had planned to see [Robert Yang](https://twitter.com/radiatoryang)'s
presentation on sex in video games, and had planned my train journey to
Copenhagen with time to spare. When stopped at some random small-town
station, we're informed that a tree fell on the tracks, and thrown out
of the train. Together with hundreds of other confused people, I
waited 3 hours for a [train-replacement
bus](https://en.wikipedia.org/wiki/Rail_replacement_bus_service) that
never came. The tracks were cleared, and trains were running again
before a bus towards Copenhagen came. Good job [DSB](https://www.dsb.dk/).
The remaining journey to Copenhagen was spent in a stuffed train,
where even first-class passengers were standing. After arriving in
Copenhagen, I still had to walk an hour to get to TAP1, the game jam location.
## Friday ##
Similar to in [2016](/website/doki-doki-densha-sekai), my friend
[Sketchwhale](http://takunomi.space) and I had already talked about
some game ideas before the jam, and just like last time, we ignored
the theme completely.
The idea we settled on was _murder-mystery dating-sim, set in an
elevator_, which Sketchwhale had called _"This- This is awful- It's not
even a real mystery"_. We would focus on the dialog between the main
character, detective _Dave Monaghan_, and the other characters. The joke was
that the murderer was obvious, but the real game lie in becoming
friends with the characters. We used a pretty awful custom built 3d engine,
I'd made earlier in the year (2018).
![A lightly-clothed girl, with pink ponytail stands in front of a blue
and black background.](/website/images/nijousatsujikenriron-day-1.png)
The jam started late, somewhere around `21:30`, and so the progress
after day one was pretty rough, as can be seen above. We had a
sprite for one character, _Miko_ and some very colorful
walls. The dialog options on-screen was baked in, and there was no
interaction beyond rotating between different clones of Miko.
## Saturday ##
Since 2017 _Nordic Game Jam_ has been a vegetarian event. I have no
issue with vegetarian food, I can live fine without meat. What I don't
care for, is being served [skyr](https://en.wikipedia.org/wiki/Skyr)
natural for breakfast, when a bowl of cornflakes or havregryn would
have done just fine. Why go for extreme variety, when something so
normal and cheap is already vegetarian?
![The same girl as before, standing in the corner of two walls,
colored in triangles. The girl is saying "...Yes?". On the left side,
the player can choose a question to
ask.](/website/images/nijousatsujikenriron-day-2.png)
Most of the game was implemented on the second day, Saturday.
Sketchwhale drew the remaining characters, and wrote the dialog for
_Miko_ and the dog. I implemented the dialog system, including all of
the _Miko_ dialog.
The 3d engine is, as previously asserted, a bit rough. It calculates
texture coordinates wrong, so the act of looking around will change
how a texture is draw, when the texture fills a large amount of the
screen.
This is obviously incorrect, but I couldn't be bothered
with fixing it before the jam, and didn't have time under the jam.
![The picture of a guy patting his head with a towel, projected onto a
surface in 3d space. The camera is looking at the picture from an
angle. The projection is weird and
distorted.](/website/images/3d-engine-stretching-issue.png)
Above is an example of the stretching bug. Compare it with [original
image](/website/images/sweat-guy.jpg). Notice how large his head is on
the projected surface, compared to how large it is on the original.
One way to avoid extreme stretching of the texture, is to split one
triangle into several. The distortion is limited, as each triangle
fills less of the screen. Unfortunately the entire engine is such a
mess, that all my attempts failed with weird warping textures.
Sketchwhale had drawn a great wall texture, but due to the stretching
bug, we could not get it to work properly. Instead we made the walls
randomly colored triangles, which looks alright.
Sketchwhale knew a musician at the jam, [Mikko "Mishicu"
Aaltio](https://twitter.com/mishicumusic). Although Mishicu were
already working with another team, he was convinced to make some music
for us, based on [that one scene from
Drive](https://youtu.be/Kq2a7MWbmJU?t=1m28s). Mishicu did a great job,
and I encourage you to play the game through, if only to listen to the music.
## Sunday ##
The third day started with incredible pressure to get the game
finished. We started work around `10:00`, with a deadline of `13:00`.
Sketchwhale mainly worked on a bit of promotional material, like a
video, while I implemented the dog dialog, and implemented an
introductory scene. A fun change was to shorten the dialog options
when not selected. This was to accommodate some long dialog options
pushing other options off of the screen.
![A cybernetically enhanced dog sitting in a corner of the elevator.
The player has several options when talking to it, some of which are
cut off, to save screen space.](/website/images/nijousatsujikenriron-day-3.png)
We didn't have time to finish the following, during the jam:
- The timer mechanic never went anywhere, as we forgot to add an
ending.
- The score mechanic was incomplete, due to a bug in the dialog
system, where some points weren't given correctly.
- One of the characters has no dialog.
- The player was supposed to have a gun, and be able to shoot
characters.
- A wireframe minimap was supposed to help the player when they
felt lost.
## The presentations ##
After the jam, every group had to present their game, in front of 30 other groups,
before voting on everybody's favorite. My favorite games from our
presentation scene was:
- [Rage Against the Cuisine](https://d-lo.itch.io/rage-against-the-cuisine)
- [Puppet Improv Theatre](https://saracecilia.itch.io/puppet-improv-theatre)
- [On-line](https://mrjwolf.itch.io/on-line)
All three groups were great at presenting, and displayed the charm of
their games very well.
I didn't get to see the final presentation, or know who won, as I left
early. I was incredibly tired, and just wanted to get home.
## Post-jam ##
After the jam, I decided to fix some of the bugs and missing features. I
added an ending, and fixed the score bugs. Furthermore a proper title
screen was added.
The introduction sequence was heavily modified, to make it more
intuitive. The doors were made actual 3d objects, and the light
flickers in a more realistic manner. A fun change was for each
character's name to only appear once the player has spoken with them.
![Elevator doors are open to an unusually large elevator. Each of the
four characters are standing in their respective corner of the
elevator.](/website/images/nijousatsujikenriron-post-jam.png)
Please do try the game; it is entirely free, and can be
[downloaded above](#download).

View File

@ -0,0 +1,86 @@
# Suggest-require
**Suggest-require** is a tiny Lua library, for discovering importable
modules for Lua's `require` function. The intended purpose is
as a part of an auto-complete system for Lua written in Lua. The
script can, when run as a standalone program, list all of the
available modules in the current environment.
The library has been tested with LuaJIT and Lua 5.1 under Linux.
Compatibility with Windows, MacOS and other Lua versions is possible,
but not assured.
Source code on [Gitfub](https://gitfub.space/Jmaa/suggest-require). Usage and examples are available in the source file itself. License is Beerware.
## Why suggest-require? ##
I have been writing a debugging shell in LÖVE for a while now. The
shell itself, called Xenoterm, is pretty powerful at this point, with complex
interactions and autocompletions, inspired by [Fish shell](https://fishshell.com/).
One of Xenoterm most powerful features is argument auto-completion,
where the shell detects which function is being tab-completed on, and
suggests several possible arguments. This is similar to when Fish
provides suggestions for command-line options, listing files in the
local directory, or password files for
[pass](https://www.passwordstore.org/). This allows the user to
offload the need to remember specific names or files, and allows them
to focus on more important things, like writing code.
![Using suggest-require within Xenoterm to autocomplete the Posix
module.](/website/images/suggest-require-2.png)
Argument completion <abbr title="reason for being" lang="fr">raison d'être</abbr>
was to make life easier for me and
[Sketchwhale](http://takunomi.space) while working on our games, as we
had a habit of forgetting the ids of items and enemies.
For obvious reasons, argument autocompletion makes most sense for
functions with a single string argument, and a limited number of
inputs. Giving autocompletions for `string.lower` would not make any
sense. A prime candidate from Lua's standard library was `require`,
Lua's module importing functionality, which is why I wrote the
suggest-require library written back in 2017.
## How is suggest-require implemented? ##
A curious thing about Lua is that it aims to be [POSIX
compatible](https://en.wikipedia.org/wiki/POSIX) in order to be as
portable as possible. This means pretty much no built-in knowledge of
filesystems. Instead, Lua stores any information about the file system
configuration in the `package` global: Directory separators, library
locations, and so on. Depending upon which platform your Lua is
compiled for the proper values are fitted in, but all of this can be
inspected and modified at runtime. `require` will update its behaviour
based upon the values in the table. So if you wanted to figure out the
importable modules, you have all the information you want.
Unfortunately, Lua is __very__ filesystem agnostic, to the point of
having no API for looking up files in a directory. The
[Lua Filesystem Module](https://keplerproject.github.io/luafilesystem/)
exists for filesystem lookup, but I don't like dependencies for a
simple script. Lua does have the `io.popen` function for
interacting with the system's shell, and this can be used to query the
filesystem. On Unixes, we use the `find` program to find files, and
its builtin pattern matching allowed a bit of a speedup.
![Using suggest-require along with grep to find all importable posix
modules](/website/images/suggest-require-1.png)
So the entire process is roughly:
1. Produce glob patterns, based on information in the global `package` table.
2. Use `find` to execute those globs, retrieving a list of possible
libraries.
3. The library paths in the `package` table may contain multiple
wildcards (marked as `?` in the path), which, when using `require`
is replaced with the requested module. Thus our glob approach finds
too many files, and we need to prune some of them, (so `./?/?.lua`
matches `./a/a.lua`, but not `./a/b/.lua`.)
4. Add the names of the already loaded libraries into the mix; these
are easily found by looking in the global `package.loaded` table.
Sugggest-require will thus most likely only work on desktop computers,
and other full featured environments. These are also the environments
where I could see the script being used; a script deep in a game
engine or on an embedded device will probably know exactly which
modules to import.