---
title: Quick Start
navTitle: Quick Start
slug: guides/quickstart
kind: tutorial
section: Guides
order: 110
status: active
summary: Create a field, display it with a formation, and explore rules that generate complex patterns.
---

# Quick Start

Welcome to this short introduction to Utomata. We'll create a field, display it with a formation, and explore simple rules that generate complex patterns. No prior experience with Utomata is assumed, and no traditional programming background is required.

> ### WARNING!
> **Photosensitivity warning:** Utomata can produce rapid flashing, flicker, and high-contrast animation that may trigger seizures or other adverse reactions in photosensitive users.

## The environment

![The Utomata environment](../images/hello-utomata.png)

The editor has three main areas and a toolbar:

**Editor** — the code panel on the left. This is where programs live. There is no compile button: valid changes take effect immediately in the running system.

**Viewport** — the live GPU output on the right. Scroll and drag to move the camera using one of three viewing modes: ORBIT, FLY, and PAN.

**Terminal** — the panel below the editor. Project settings, compile results, and messages appear here. If something is wrong, this is where it says so.

The **transport** bar at the bottom controls the running program: reset, play/pause, step, clock rate, and live diagnostic data.

## Fields and Formations

Paste the following program into the editor:

```uto
#A {
  dim = (64, 64, 1);
  set = rand(1,2,3);
}

~A { col = #A; }
```
[Run this sketch](https://uto.run/AU2Py27bMBBF_-V6kwADQZTVIKHhhfMCCiQoULfdBFpQ4kghQpEGSSUtDOXbCzrOY8PFnZnDc_d4hhSEyCkZN0TIPZwaGRK_XTLJskaesoaEqJb1NxCSCgOn212EFBVBdck88x_DLzsfEiQ092qyCYROjRxUhu58NMl4B_lQUklVUYu6at5Zx7RsCKPX-fcfPy-__8JMGILR92_Z338g9D6MKpPuVMs2QvbKRiZ03qXgbbxxqs3WMoWJCZMz-SJCPjSEwE5z2H4p26ruaQh-cjo7FOU5HZ9ltrNmeEzXJhz9RENQY2vYpW0K7Ib0CFkWS4I2fT9F_kzFx-aVt_4AKC5IUFlcNB_r7yNB4sDWfmotb43O_ode80yIfgpd7r_Y7LUZ1ydnNZ3VJE5XkdM6KKdPBFW0PF2Fya0Xq_l1s--8XS82qxnzfw "rand(1,2,3)")


`#A` is a named **field** — a grid of cells with 64 columns on the x axis, 64 rows on the y axis, and one layer on the z axis. Every cell stores one three-channel value, called a vector. Vectors are the universal value type in Utomata: the same three channels can represent color, position, rotation, counts, or any other quantity.

`set` is evaluated **once**, when the field is configured or reset. It returns one vector **for every cell in the field**. `rand(1,2,3)` generates an unsigned seeded random vector independently for each cell; the three seeds produce independent values between `0.0` and `1.0` for its three channels.

`~A` is a named **formation** — a visual projection of field data. Its `col` property reads `#A` and uses the field values as RGB color. Fields compute; formations project. Keeping those roles separate means the same field can be visualized in different ways, and several fields can contribute to the same formation.

Utomata is **strictly parallel and bottom-up**. Every cell computes its own value independently, and nothing directly writes to anything else. There is no central controller moving data around the system. Global behavior emerges from many local computations running in parallel.

## Math and Memory

Add a third property to `#A`:

```uto
#A {
  dim = (64, 64, 1);
  set = rand(1,2,3);
  run = #; // <-- add this
}
```

Like `set`, `run` is evaluated for every cell simultaneously. Unlike `set`, however, `run` is evaluated at **every clock tick**.

The `#` symbol is used to read field values. On its own, it means *the current value of this cell*, so this program simply tells every cell to keep its current value.

Now change it to:

```uto
run = add(#, 0.01);
```

Expressions in Utomata use **prefix notation**, where the operation comes first, followed by its inputs. Instead of `2 + 2`, we write `add(2, 2)`. This gives Utomata expressions a minimal and regular syntax: operations compose in exactly the same way whether they take one, two, or several inputs, and operation names are kept to three letters so that deeply nested expressions remain compact and easy to scan.

Notice that `#` is a three-channel vector while `0.01` is a single number. In Utomata, single values and vectors can be freely combined: a single value is applied equally to all three channels. This makes it possible to work with vectors without constantly spelling out all three components. The following statements  all equivalent:

```uto
0.01
(0.01)
(0.01, 0.01)
(0.01, 0.01, 0.01)
```

More generally, Utomata uses *lifting* and *swizzling* to allow operations between vectors of different dimension.

```uto
(1)       => (1,1,1)  // y and z channels are lifter from x
(1, 2)    => (1,2,2)  // z channel is lifted from y
(1,2).xyx => (1,2,1)  // swizzle allows explicit assignment
(1,2,3).z => (3)      => (3,3,3)
```

Because `run` is evaluated at every tick, it can update cell values over time. in our current example, every cell adds `0.01` to its current value at each step. At a typical rate of 60 ticks per second, the field quickly becomes saturated as its RGB values approach `(1.0, 1.0, 1.0)`. To resolve this saturation we can keep cell values cycling:

```uto
run = frc(add(#, 0.01));
```

`frc()` returns only the fractional part of its input. When a channel reaches `1.01`, for example, `frc(1.01)` returns `0.01`. Instead of increasing indefinitely, each channel now wraps continuously through the unit interval.

Utomata also exposes the current clock count as `step`. Its value increases by 1 on every tick, so it can be used anywhere an expression needs to keep track of time:

```uto
rand(step)
rand(step, add(step, 1), add(step, 2))
```

Using `step` as a random seed produces a new but deterministic value on every tick. It can also drive operations such as `sin()` and `frc()` directly, without having to read previous field state.

Here are a few common operations to experiment with:

| Operation | Example | Meaning |
| --- | --- | --- |
| `add` | `add(#, 0.01)` | add values |
| `sub` | `sub(#, 0.01)` | subtract |
| `mlt` | `mlt(#, 0.99)` | multiply |
| `div` | `div(#, 4)` | divide |
| `sin` | `sin(#)` | apply sine |
| `mod` | `mod(#, 0.25)` | apply a modulo |
| `abs` | `abs(#)` | absolute value |
| `frc` | `frc(#)` | fractional part |

The full set of operations is listed in **manual/foundations**.

At this point, try experimenting with `run` freely. Combine `#`, `step`, static values, vectors, and mathematical operations and explore what happens.


## Space and Time

So far, every cell has only read its own value. Let's make it look at something else:

```uto
run = #(-1, 0);
```

`#(-1,0)` is a **relative lookup**. It reads one cell to the left on the x axis and zero cells on the y axis. The cells themselves never move. Instead, the values they hold propagate through the grid. Because every cell performs the same lookup simultaneously, the entire field appears to travel at exactly one cell per tick.

Try using different lookup coordinates:

> For this section it might be useful to slow the clock down in the transport bar, otherwise results can flicker quite a bit.

```uto
#              // my own value
#(-1, 0)       // one cell to the left
#(2, 2)        // two cells down and to the right
#(-10, 12.34)  // lookup coordinates are rounded
#(64, 65)      // coordinates beyond the field wrap around
```

Lookup coordinates are not restricted to static numbers. They are expressions like anything else in Utomata.

For example:

```uto
run = #(rand(step), 0);
```

Now the x offset changes on every tick. Instead of propagating uniformly in one direction, every cell follows a lookup relationship that changes over time.

Because `rand()` returns values between `0.0` and `1.0`, the rounded lookup can only select the current cell or its neighbor on the positive x axis. We can extend it in both directions with `srand()`:

```uto
run = #(srand(step, add(step, 1), 0));
```

`srand()` returns signed values between `-1.0` and `1.0`. Here the first seed, `step`, drives the x component of the offset while the second, `add(step, 1)`, privdes a different seed for y.

The important point is not randomness itself. The coordinates inside `#(...)` can contain **any expression**:

```uto
#(sin(step), 0)
#(mlt(sin(step), 10), 0)
#(srand(step), sin(step))
```

A lookup can therefore change continuously with time, mathematics, field data, or combinations of all three. This is where relative lookup becomes more than a way to access neighboring cells: the relationships between cells can themselves become part of the computation.

## Recursive Lookups

There is one more step we can take.

A lookup expression can also contain more field lookups:

```uto
#A{
  dim = (64, 64, 1);
  set = rand(1,2,3);
  run = #( # );
}

```

This tiny expression changes the nature of the system.

The inner `#` retrieves the current value of the cell, while the outer `#(...)` then interprets that value as a relative coordinate. Each cell is therefore using its own state to determine which of its neighbors to look at.

This is an important idea in Utomata: **field values do not have to represent only flat color states. They can also become coordinates, offsets, parameters, and inputs to further computation.**


We can adjust the lookup range by applying operators:

```uto
run = #(mlt(#, 4));
```

The rule is still the same in principle — *use my value as an address* — but multiplying that value expands the region from which each cell can retrieve its next state.

Now try moving the inner read away from the cell itself:

```uto
run = #(#(-4, 20));
```

This creates a second-order lookup.

First:

```uto
#(-4, 20)
```

reads the value of another cell.

Then the outer:

```uto
#(...)
```

uses that retrieved value as a coordinate for a second read.

Each cell is no longer deciding where to read based on its own state. **It is using the value of one of its neighbors to retrieve the value of another one.** But keep in mind — those neighbors do the same with their neighbors, and so on...

To give the system equal access to positive and negative directions, change the initialization to `srand()` as well — and while we're at it, enlarge the field for more detail:

```uto
#A{
   dim = (256, 256, 1);
   set = srand(1, 2, 3);
   run = #( #(-20, 40) );
}
```

The resulting behavior can become surprisingly intricate, but the program remains extremely small. There is no hidden controller and no sequence of commands directing the pattern. Each cell repeatedly performs the same nested lookup using the current values of its neighbors. All cells together, 60 times per second.

The system is also entirely deterministic. Given the same initial state (`set`) and the same cell update rule (`run`), the field will exhibit the exact same evolution every time, even after thousands of steps.

From here, there is no single correct direction to explore. Try different combinations:

```uto
#(#)
#(mlt(#, 4))
#(#(1, 0))
#(#(-4, 20))
```

Insert mathematical operations into the inner and outer expressions. Change the initial field. Change the scale. Change which neighbor provides the address. Bring back `step` or the `rand()` operator to modulate the outcome.

Small changes to these expressions can describe very different systems. This is possible because the behavior of such systems *emerges* from the interaction between their constituent parts. 

## What we just learned

In this short guide we have used many of the core pieces of a Utomata program:

```uto
#A        // field
~A        // formation

set       // initial state of each cell
run       // value computed at every step

#         // current value of the cell
#(x,y)    // relative field lookup

rand()    // unsigned seeded random value
srand()   // signed seeded random value
step      // current clock step

add(x,y)  // mathematical operation
```

This combination of **field reads, mathematics, and nested lookups** is one of the central ideas in Utomata. The syntax stays small while the systems it describes can become extremely complex.

By changing only a few expressions, we moved from static random color to feedback, mathematical recurrence, spatial propagation, changing relationships between cells, and finally systems whose own state determines how they are connected.

Everything in this tutorial happened inside one field, projected onto one formation. A Utomata program can contain many fields, each performing a different computation — and every cell of every field can look at any cell of any other.

From here, you can visit the **Guides** section, read the **Manual**, or explore the **Examples**. 
