Meet the Toplevel

Before we draw a single pixel, meet the tool you'll use every day of this quest: a live conversation with the OCaml compiler — running right here in this page.

You will be able to…

Your first spell

The box below is a real OCaml 5.5 engine, compiled to JavaScript so it runs inside your browser. Nothing to install. Press Run (or Ctrl+Enter) and watch what comes back.

The engine answers something like:

Read it right to left: the value is 2, and its type is int (a whole number). The - just means "you didn't give this a name". In OCaml, everything you type is an expression, and every expression evaluates to a value with a type. That sentence is half of this whole course.

The four starter types

Games juggle numbers, text and yes/no facts all day: scores, speeds, player names, "is the door open?". Here's how OCaml spells them — this is a transcript of a toplevel session (the # is the prompt, like the $ in a shell):

Yes, + and +. are different operators, and OCaml refuses to mix them. Let's break it on purpose — run this and read the error like a detective:

The compiler says the 2.5 has type float but was expected to have type int, because + only works on ints. This strictness feels fussy today; by Phase 2 it will be catching your game bugs before they exist. To fix it you'd write 1.0 +. 2.5 — or convert: float_of_int 1 +. 2.5.

Naming things with let

Answers marked - vanish into the sand. To keep a value, bind it to a name:

Now the answers read val lives : int = 3 — a named value. Time for your first real exercise. From here on, the Check button compiles your code in a fresh environment and runs hidden tests against it. Green means XP.

Define a value named answer equal to six times seven. Use the multiplication operator, not the number 42 itself — let the machine do the maths.

The pattern is let name = expression.
Multiplication for ints is * : try let answer = 6 * 7.

A health potion holds 2.5 litres. Your hero drinks three of them, plus a 0.25-litre espresso of courage. Define litres, a float with the total amount drunk. Remember: float operators wear a dot.

Multiply with *. and add with +. — both need the dot for floats.
2.5 *. 3.0 +. 0.25 — note 3.0, not 3: no mixing ints into float maths.

Strings: the ^ glue

Text joins with the caret operator. Run this, then make it your own:

Keep the given hero binding. Build battle_cry so it reads exactly For Camelot and Maks! — using ^ and the hero value, not by typing the name again.

Three pieces: "For Camelot and ", the hero, and "!".
"For Camelot and " ^ hero ^ "!" — mind the space after and.

Saying it out loud: print_endline

The - : type = value answers are the toplevel being helpful. To make your program actually print — like a game printing "LEVEL UP!" — call print_endline, which outputs a string plus a newline:

That let () = looks odd for now — read it as "do this, keep nothing". print_endline returns the boring value () (type unit, OCaml's "nothing to report"), and we bind it to the pattern () to say we expected that.

Print exactly these two lines, using two print_endline calls:

The tournament begins!
Player one: ready
Two separate let () = print_endline "…" lines, in order.
Match the text exactly — capital letters, the colon, the exclamation mark.
Deeper: can I change a let later?

No — and that's a feature. A let binding is not a variable-in-a-box like in Python or JavaScript; it's a name for a value, forever. You can shadow it (bind the same name to a new value), but the old value never mutates behind your back. Phase 2 builds entire game worlds on this idea: instead of changing the world, you compute a new world every tick. Determinism, replays and fearless refactoring all fall out of it.

Checkpoint quiz

Loot collected

Next: teach the machine new tricks — functions, the verbs of your game.