The .Wat ness is open for testing!

http://watness.pwni.ng:7744/

When it came out in 2016, the Witness impressed with its ability to gradually teach new players the rules of the game by simply having them play it. With the .Wat ness, we take this just a small step further.

## How to solve

**First of all, this write-up has a lot of guesses**.

Also, teammate imnotkind helped in downloading resources and reversing typescript files!

### Super easy guesses

If you’re a ‘the witness’ player, you can easily guess four symbols: (Read this with the guide)

– Multicolored squares in the Witness

– Suns in the Witness

– Tetris blocks in the Witness

– Triangles in the Witness

Wait, why the guide does not explain triangles? You need to draw a path exactly passes *n* edges of the block with *n* triangles. In The .Wat ness, it is *n* blue blocks.

But what are those?

We need to figure them out…

### Reversing

Download all resources via Save All Resources.

By reading `src/constraints.ts`

, you can know there are total 6 constraints and `Constraint5`

is reversed triangles, and `Constraint6`

is round-edged rectangle.

By reading `problem/common/src/bootstrap.ts`

, you can see four parameters are passed to `fn_assembly/index/checkAll`

. (In the code, it is `this.module.checkAll`

.) If `checkAll`

returns an empty array, it is the answer. So, what are those four parameters?

- mtx (parameter 1) : array_BoardMatrixElement - parts (parameter 2) : array_PartitionListElement - horizontalPathSegments (parameter 3) : array_i32 - verticalPathSegments (parameter 4): array_i32

The first parameter describes the symbols on the board.

If the board is partitioned by the input path, partition information is passed by the second parameter.

The third and fourth parameter have which edge is passed by the input path. So, the third one will be kinda 7×6 matrix, and the fourth one will be 6×7 matrix.

I’ve run wabt wasm2c to read the wasm file.

`checkAll`

calls `Constraint{i}_check`

functions. Let’s see `Constraint6_check`

.

When reading the code, `p{i}`

is the ith parameter, `l{i}`

is a local variable, and `l{i}`

is a temporal variable. Just understand `l{i}[/jscas non-volatile registers, and [c]i{i}`

as volatile registers.

static u32 assembly_index_Constraint6_check(u32 p0, u32 p1, u32 p2, u32 p3) { u32 l4 = 0, l5 = 0, l6 = 0, l7 = 0, l8 = 0; FUNC_PROLOGUE; u32 i0, i1, i2, i3; i0 = 0u; i1 = 0u; i0 = _lib_array_Array_Constraint__constructor(i0, i1); l4 = i0; i0 = 0u; l5 = i0; L1: i0 = l5; i1 = p0; l6 = i1; i1 = l6; i1 = i32_load((&memory), (u64)(i1 + 4)); i0 = (u32)((s32)i0 < (s32)i1); i0 = !(i0); if (i0) {goto B0;} i0 = 0u; l6 = i0; L4: i0 = l6; i1 = p0; i2 = l5; i1 = _lib_array_Array_Array_BoardMatrixElement_____get(i1, i2); l7 = i1; i1 = l7; i1 = i32_load((&memory), (u64)(i1 + 4)); i0 = (u32)((s32)i0 < (s32)i1); i0 = !(i0); if (i0) {goto B3;} i0 = p0; i1 = l5; i0 = _lib_array_Array_Array_BoardMatrixElement_____get(i0, i1); i1 = l6; i0 = _lib_array_Array_BoardMatrixElement____get(i0, i1); i0 = i32_load((&memory), (u64)(i0 + 4)); i1 = 0u; i0 = i0 != i1; l7 = i0; if (i0) { i0 = p0; i1 = l5; i0 = _lib_array_Array_Array_BoardMatrixElement_____get(i0, i1); i1 = l6; i0 = _lib_array_Array_BoardMatrixElement____get(i0, i1); i0 = i32_load((&memory), (u64)(i0 + 4)); i0 = i32_load((&memory), (u64)(i0 + 12)); i1 = 2344u; i0 = assembly_index_streq(i0, i1); } else { i0 = l7; } if (i0) { i0 = p0; i1 = l5; i0 = _lib_array_Array_Array_BoardMatrixElement_____get(i0, i1); i1 = l6; i0 = _lib_array_Array_BoardMatrixElement____get(i0, i1); i0 = i32_load((&memory), (u64)(i0)); l7 = i0; i0 = p2; i1 = l5; i0 = _lib_array_Array_Array_i32_____get(i0, i1); i1 = l6; i0 = _lib_array_Array_i32____get(i0, i1); i1 = p2; i2 = l5; i3 = 1u; i2 += i3; i1 = _lib_array_Array_Array_i32_____get(i1, i2); i2 = l6; i1 = _lib_array_Array_i32____get(i1, i2); i0 += i1; i1 = p3; i2 = l5; i1 = _lib_array_Array_Array_i32_____get(i1, i2); i2 = l6; i1 = _lib_array_Array_i32____get(i1, i2); i0 += i1; i1 = p3; i2 = l5; i1 = _lib_array_Array_Array_i32_____get(i1, i2); i2 = l6; i3 = 1u; i2 += i3; i1 = _lib_array_Array_i32____get(i1, i2); i0 += i1; l8 = i0; i0 = l8; i1 = 0u; i0 = i0 != i1; if (i0) { i0 = l4; i1 = p0; i2 = l5; i1 = _lib_array_Array_Array_BoardMatrixElement_____get(i1, i2); i2 = l6; i1 = _lib_array_Array_BoardMatrixElement____get(i1, i2); i1 = i32_load((&memory), (u64)(i1 + 4)); i0 = _lib_array_Array_Constraint__push(i0, i1); } } i0 = l6; i1 = 1u; i0 += i1; l6 = i0; goto L4; UNREACHABLE; B3:; i0 = l5; i1 = 1u; i0 += i1; l5 = i0; goto L1; UNREACHABLE; B0:; i0 = l4; FUNC_EPILOGUE; return i0; }

`L1`

and `L2`

are loop labels. Each uses `l5`

and `l6`

as an iterator.

The key part is Line 55-104. It checks whether any edge around the block is passed by the input path. If yes, it will return those blocks as `array_Constraint`

.

The return value should be an empty array, so round-edged rectangle symbols are like blue blocks symbols with *zero* blue blocks. We need to avoid four edges around round-edged rectangles, regardless of its color!

Then, what are reversed triangles? Well, **I don’t know**.

It’s still solvable without knowing it. Just try all the possible paths around reversed triangles. One of them will be a solution.

### Solving

Just do by your hands. If it seems hard to solve, just press F5. I solved all the stages within 2 minutes.

The flag is `pctf{what_if_i_made_firmament_instead}`

.

BTW, I solved all the puzzles in the Witness.