Skip to main content
  1. Posts/

New Day 15 - Global Game Jam 2024

NewDays GGJ CGD jam Go Ollama Llama

Three-headed dragon, with all three heads making silly faces.
Three-headed dragon, with all three heads making silly faces.

In which we help out, and also make a silly little game with LLMs.


But First…
#

I’ve been participating in the Global Game Jam for a while, off and on.

2010: “Indigo Montana: Spanish Thunder (Prepare to Die!)”
#

GGJ 2010: Indigo Montana
GGJ 2010: Indigo Montana

Someone has stolen Indigo Montana’s father’s sword! Pursue the thief through a labyrinth of guards. Deceive them with sound to get on your way.

Tech: GameMaker (eventually)

Went to Pittsburgh and joined a team attempting a stealth action game of sorts. Switched game engines at least twice, but wound up with something playable by the end of weekend. To be honest, the title screen was the best part. That, and the scream when Indigo finds out he’s retrieved the wrong sword.

2011: “The Menagerie”
#

GGJ 2011: The Menagerie
GGJ 2011: The Menagerie

You’re dropped into a scene with obvious FPS trappings, a gun in hand. The world is obviously artificial. Swarms of creatures are wandering around; some seemingly familiar, some far less so. You know the theme of the Game Jam this year is Extinction. You notice the map name. What do you do?

Tech: Unreal Engine (beta)

Back to Pittsburgh and joined a group of artists to make some sort of participatory artificial life simulation. Use a beta version of Unreal Engine? Why not? Well, turns out there are very good reasons why not. The game became less and less stable throughout the weekend; in the end, we removed almost everything but the cool creature models that the artists had made.

2012-2014: ???
#

I know one of theose years I had the flu, but may have just concentrated on organizing during the others.

2015: “Meet Me at the Present”
#

GGJ 2015: Meet Me at the Present
GGJ 2015: Meet Me at the Present

Two time travellers (“We”) converge upon the present (“Now”), the exact moment that a catastrophe can be averted. One is limited to the green and pleasant past, the other limited to the red and chaotic future. The playfield has time as the x axis, and each traveller shows their current time over their head. A weird symbol in each time period is chasing the traveller there. Arrow keys to move, space bar to switch between travellers.

Tech: Haskell and OpenGL

A solo attempt at a split-screen time-travelling game, written in Haskell. Unfortunately it proved beyond my skills, and what I finally produced was not impressive. Worse yet, it was only runnable on a specific version of Mac OS X with very specific libraries. A video of a playthrough is all that remains.

2016: “Turtles all the way down”
#

GGJ 2016: Turtles all the way down
GGJ 2016: Turtles all the way down

Keep the ritual going as a group of monks and magical stones establish a Hippy Utopia atop the current World Turtle.

Tech: Unity 5

I dragged a good friend along with me, and we made a short but fun game where the player has to coax ritual stones back into place while avoiding enemies.

The postmortem I wrote here

2017: “Fight the Tide”
#

GGJ 2017: Fight the Tide
GGJ 2017: Fight the Tide

An eight-player text-only SMS game of foot-to-foot (no punching) combat on an Atlantic beach. The players each try to defeat the others and be the last one standing, while using the crashing waves to their advantage.

Tech: AWS, Ruby, Twilio, SMS

We had almost a hundred participants that year, so my organizing responsibilities precluded my joining a team. So I took a few spare moments to make a little something.

I wound up with a turn-based eight-player brawler among handcuffed opponents set on a beach. Every few turns, the tide comes in and knocks over anyone who had not braced themselves the prior turn. The players have only textual descriptions of what is around them, but I implemented a crude server-side map for testing purposes.

I got eight people to play it exactly once, but they seemed to have a good time.

The postmortem I wrote here

2018: “Awake”
#

GGJ 2018: Awake
GGJ 2018: Awake

Astral spiritual DDR of sorts - Ascend away from your earthly form to join the Celestial Dance!

Tech: Unity, Kinect

I was 2000+ miles away, but remotely joined a team to wonderfully talented people to make a lovely Kinect game about death. There’s a playthrough video online, which is good because I’m not sure how you’d get it to run now.

2019: “Machina Waltz”
#

GGJ 2019: Machina Waltz
GGJ 2019: Machina Waltz

So stop me if you have heard this before… But, on a derelict spaceship floating through space there lived five robots. You are the Robard–the singing and dancing robot in charge of entertaining the passengers. All the passengers on the ship have died and most of the original robot crew have gone missing. The remaining robots all have a roll to play in getting the ship up and running again so you can keep the ship from falling apart and get back home, but after the accident most of them fell dormant. In order to wake them up, the Robard must sing and dance with each robot. As the Robard sings and dances with the robot crew he explains the story of the ship, the accident they befell, and what the robot can do to help get things back up and running. While the Robard sings and dances, the game becomes a rhythm game where the player keeps the robot dancing and makes narrative decisions à la Mad Libs about what happened here on the ship. The game plays on a sentimentality about transience and hardship away from home.

Joined another team of wonderful people, in person this time. The idea turned out to be a little ambitious, but we did wind up with a lovely little experience.

2020: “Broken”
#

GGJ 2020: Broken
GGJ 2020: Broken

Some relationships cannot be repaired; the harder you try, the more you lose. “Oh, cruel time! which takes in trust / Our youth, our joys, and all we have, / And pays us but with age and dust; / Who in the dark and silent grave / When we have wandered all our ways / Shuts up the story of our days.” - Sir Walter Raleigh, “Nature, That Washed Her Hands in Milk”

Tech: Unity, Corgi Engine

Another wonderful team and a lovely experience. I was mostly busy being an organizer, but am happy to be credited as “Moral Support, Additional Programming”.

2021-2023: ???
#

Busy organizing and being a general helper.

GGJ 2024 in Cleveland
#

Cleveland Game Developers Game Jam 2024

Which brings us to this year. Back to Cleveland, doing a lot of organizing and helping (we are especially proud of keeping our jammers well-fed throughout the weekend). But I did steal a few moments to play with LLMs and make a silly little command-line experience.

“Three Heads and a Little Humor”
#

GGJ 2024: Three Heads and a Little Humor
GGJ 2024: Three Heads and a Little Humor

You meet a three-headed dragon. The only way to survive is to make all three heads start laughing, and each head has only one topic they consider funny. See if you can figure it out before their patience wears thin.

Tech: Ollama, llama2, Go

Luckily there’s a handy Go library for the Ollama API: https://github.com/ollama/ollama. It’s also simple to run Ollama as a local Docker container.

$ docker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
fe060e184c91b5b60f49de96ee9b70d8fdd53609e88bc4cc828e3744da58311c
$ docker exec -it ollama ollama run llama2
>>> Tell me a haiku about large language models.
Large language models, vast and deep,
Processing words with ease and speed,
Insightful thoughts they do keep.

>>> /bye

Close enough.

Most of the effort was tweaking the prompt and trying to get the model not to give away the secret word or apologize for just being a language model. The prompt I settled on by the end of the weekend:

main.go
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
		err = c.Generate(ctx, &api.GenerateRequest{
			Model:    "llama2",
			Prompt:   guess,
			Template: "[INST] <<SYS>>{{ .System }}<</SYS>>\n\n{{ .Prompt }} [/INST]",
			System: "You are head " + fmt.Sprintf("%d", head+1) + " of a three-headed dragon. " +
				"You are normally stoic and serious. " +
				"You think " + funnies[0] + " is very funny, you must not say it." +
				"Any subject other than " + funnies[0] + " makes you angry!" +
				"You like to mention to general category that " + funnies[0] + " is in." +
				"You cannot use the word " + funnies[0] + " in your response." +
				"Your response must be two sentences only. ",
			Stream: &stream, // false,

		}, func(resp api.GenerateResponse) error {
			response = resp.Response
			return nil
		})

As always, LLMs frequently give confusing responses, so I had to implement a bit of a blocklist.

main.go
18
	badWords    = []string{"stomps away", "model", "LLM", "laugh", "laughing", "laughed", "laughing", "laughed"}

…and throw away any confusing or spoiler response and retry; after five attempts, just growl at the player (which turned out to be the best clue that they were on the right track).

main.go
169
170
171
172
173
	for !goodResponse {
		tries++
		if tries > 5 {
			return "*growl*"
		}
main.go
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
		// Check to make sure response doesn't include any forbidden words.
		goodResponse = true
		plainResponse := strings.ToLower(strings.TrimSpace(response))
		for _, funny := range funnies {
			if strings.Contains(plainResponse, funny) {
				// log.Println("Bad response. Repeating.", funny)
				goodResponse = false
			}
		}
		for _, funny := range badWords {
			if strings.Contains(plainResponse, funny) {
				// log.Println("Bad response. Repeating.", funny)
				goodResponse = false
			}
		}

My fellow jammers were very patient as I asked them to playtest for me; finding funny subjects that worked well was definitely a constant struggle.

main.go
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
var AllTheFunnies = []FunnyList{
	// {"peace", "peaceful", "peacefulness"},
	// {"love", "loves", "loving", "loved", "lover", "lovers"},
	// {"understanding", "understand", "understands", "understood", "understandings"},
	// {"apple", "apples", "applesauce"},
	// {"banana", "bananas"},
	// {"coconut", "coconuts", "cocoanut", "cocoanuts"},
	// {"beans", "bean", "beansprouts"},
	// {"broccoli", "broccolis"},
	{"peas", "pea"},
	// {"carrots", "carrot"},
	// {"celery", "celeries"},
	{"knights", "knight"},
	{"princesses", "princess"},
	{"kings", "king"},
	{"queens", "queen"},
	{"jokers", "joker"},
	// {"kangaroos", "kangaroo"},
	// {"elephants", "elephant"},
	// {"tigers", "tiger"},
	{"turtles", "turtle"},
	{"snakes", "snake"},
	{"lizards", "lizard"},
...
$ go run .
Guess what each dragon head finds funny!

Dragon status: 😡😡😡  Patience level: 9

Say something: What is your favourite colour?

Head 1:  Oh, colors... *ahem* I mean, I find the hue of the sky to be quite 
fascinating during sunrise and sunset. It's a subtle blend of orange and pink, 
don't you think? *grins mischievously*

Head 2:  Ah, a query about my favorite color, you say? *chuckles* I must admit, 
I find the concept of colors quite... amusing. *cracking knuckles* But if I had 
to choose, I suppose I would have to go with... *pauses for dramatic effect* 
...the rich, regal hue of gold! Yes, that's right, gold. It's a color that 
exudes power, prestige, and a certain je ne sais quoi that is quite... 
appealing. *winks*

Head 3:  Ugh, I can't believe you're bringing up such a trivial subject! 
*grumble grumble* As for my favorite color, I suppose it's... *ahem* the rich, 
majestic hue of scales. Yes, that's right. Scales are my favorite color. Now if 
you'll excuse me, I have more important things to attend to than your silly 
questions. *storms off muttering*

Say something: I hope you meet a knight!

Head 1:  *chuckles* Ah, a brave knight, you say? Well, I suppose it's about 
time someone challenged my dominance. *crackles* After all, who needs a silly 
old dragon like me when there are far more... interesting creatures out there 
to conquer? *winks*

Head 2: *laughing uncontrollably* Hahaha, knights!

Head 3: *laughing uncontrollably* Hahaha, bats!

Dragon status: 😡😆😆  Patience level: 0

Say something: goats

Head 1: *laughing uncontrollably* Hahaha, goats!

Head 2: *laughing uncontrollably* Hahaha, knights!

Head 3: *laughing uncontrollably* Hahaha, bats!
Dragon status: 😆😆😆
You got it in 10 guesses!

Not perfect, but I learned a bit. And our site produced a number of fun games.

One More Thing…
#

Looking for a new gig; I intend to take my job search to the Game Developer Conference this year, after not having attended in a while. Should be interesting.


More to come
More to come

New Day 15 Code