# My First Zig Chess Step

**URL:** <https://ziggit.dev/t/my-first-zig-chess-step/11254>\
**Category:** Showcase\
**Tags:** chess\
**Created:** [July 31, 2025, 1:32am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254 "2025-07-31T01:32:42Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [July 31, 2025, 1:32am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/1 "2025-07-31T01:32:42Z")

</div>

> **[GitHub - ericlangedijk/chessnix](https://github.com/ericlangedijk/chessnix/tree/main)**
>
> main

My Zig attempt creating an uci chess engine. The ultimate goal is to put the bot on [lichess.org](http://lichess.org).  
Move generation is already pretty fast using the ‘easy’ version of bitboards.  
Next step will probably be implementing “pext magic bitboards” to check if that speeds up even more.

The program currently measures only the speeds of 4 positions in the same way as  
this one does: [https://github.com/Gigantua/Gigantua](https://Gigantua)  
The speed of Gigantua is around 3 times higher than my code, which bothers me :). It is party because my code will be a real engine: there is more data involved than only generating moves.

Nevertheless I would be very interested in finding optimizations.  
Zig experts: I challenge you 🙂

The main activity can be found in:

- `data.get_xxx()`
- `Position.make_move()`
- `Position.gen()`
- `MoveStorage.store()`
- `funcs.pop_square()`

---

<div class="post-metadata">

**Author:** ![ppipelin](https://ziggit.dev/user_avatar/ziggit.dev/ppipelin/32/4631_2.png) [@ppipelin](https://ziggit.dev/u/ppipelin)\
**Post date:** [August 1, 2025, 9:25am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/2 "2025-08-01T09:25:20Z")

</div>

Nice work ! Did you see benefits from using `comptime` ?  
I was thinking about adding it for `Color` on my engine but I noticed you use it a lot :

```zig
fn do_run(comptime output: bool, comptime is_root: bool, comptime us: Color, depth: u8, pos: *Position) u64

```

If I understand correctly this will create one specific function per color.

Also for the output it makes sense because it would clean out some ifs, but I would assume the compiler would do that by itself no ?

I thought comptime was useful for complex logic that a compiler cannot sort out, isn’t it the case ?

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [August 1, 2025, 9:49am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/3 "2025-08-01T09:49:12Z")

</div>

Thanks.  
Yes it will monomorphize the functions: create specifics.  
I did a little measurement a while ago. I think in general “comptiming” the color to move speeds up 10-15%.

Regarding complex logic:  
In general I noticed the compiler is insanely smart. Mostly smarter than I am.  
For (for example) the generation of moves I trust it to eliminate the dead comptime code in each generated function.

Also something like:  
`const them: Color = comptime us.opp();`  
is - I believe - not a real variable in memory.

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [August 1, 2025, 9:51am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/4 "2025-08-01T09:51:09Z")

</div>

> [@ppipelin](#):
>
> Also for the output it makes sense because it would clean out some ifs, but I would assume the compiler would do that by itself no ?

I don’t think so. But I am unable to produce / verify that like inspecting the asm output.

---

<div class="post-metadata">

**Author:** ![glfmn](https://ziggit.dev/user_avatar/ziggit.dev/glfmn/32/1763_2.png) [@glfmn](https://ziggit.dev/u/glfmn)\
**Post date:** [August 1, 2025, 1:51pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/5 "2025-08-01T13:51:26Z")

</div>

I don’t know about the Zig compiler’s self-hosted backend, but in a lot of compilers or intermediate representations (and certainly in [LLVM IR](https://llvm.org/docs/LangRef.html#well-formedness) and [SPIR-V](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_static_single_assignment_ssa) for example) even your `var`s become `const` due to static-single-assignment form. This:

```zig
var i: usize = 0;
i = i + 1;
i = i * 5;

```

Becomes this:

```zig
const i_0 = 1;
const i_1 = i_0 + 1;
const i_2 = i_1 * 5;

```

This makes things like constant folding easier to implement. At a later stage, the compiler will start scheduling registers and will fold operations to re-use values again, reintroducing mutable state. I’m not an expert so I’m not sure how things like loads and stores work in the context of SSA. You can use them in SPIR-V in the same way you’d use a mutable variable (storing multiple times), but in general, mutable variables are lying to you, at least for things that can ultimately be represented as pure expressions.

---

<div class="post-metadata">

**Author:** ![jabolcni](https://ziggit.dev/user_avatar/ziggit.dev/jabolcni/32/1694_2.png) [@jabolcni](https://ziggit.dev/u/jabolcni)\
**Post date:** [August 10, 2025, 5:14am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/6 "2025-08-10T05:14:47Z")

</div>

Congratulations on your progress Eric. Much nicer code than mine. My zig code still looks more c code with zig syntax.

Move generator seems blazingly fast.

Also good decision to support chess 960 from the start. This is still on my to-do list for Lambergar.

When do you plan to implement search?

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [August 10, 2025, 9:01am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/7 "2025-08-10T09:01:32Z")

</div>

Thanks.  
I start search somewhere in the next 2 weeks, first with Handcrafted Evaluation.  
Then I check if he finds the solutions of puzzles on [lichess.org](http://lichess.org).  
(Long) after that I will maybe generate my own neural netwerk file, with the help of my smart daughter.  
Yes the movegenerator is quite fast. The pinchecks are quite ok and some comptimes also help. Still I am bothered with the fact that Gigantua is much faster.  
First I need to complete the UCI protocol.

---

<div class="post-metadata">

**Author:** ![voroskoi](https://ziggit.dev/letter_avatar_proxy/v4/letter/v/8c91f0/32.png) [@voroskoi](https://ziggit.dev/u/voroskoi)\
**Post date:** [September 20, 2025, 7:20pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/8 "2025-09-20T19:20:59Z")

</div>

Oh, I would love to figure out how we could replicate with zig comptime what happens in Gigantua with constexpr and templates. Theoretically this should be possible, but I am unable to get it done.

I have a hard time understanding Your code, so I just ask:  
In a perft function people usually do something like this:

```zig
fn perft(attacks, board, state) usize {
  moves = generateMoves(board, state, ...)

  for (moves) |move| {
    next = doMove(board, state, ...)
    nodes = perft(next.board, next.state, ...)
  }
}

```

The `state` variable holds color, castling and enpassant options if they are available, this should be comptime.

When You call doMove() You can calculate the next state based on the move: When it is a simple move You just flip the color, but when You move the rook or the king You change the castling options. So You can generate a comptime `state{color, castling, enpassant}`.

This sounds good, but as soon as You return this value as `next` in the example zig can not use it as a comptime value. Well, You can use an inline switch to make it comptime again, but that kills the whole point of knowing the return value in advance ☹

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [September 21, 2025, 7:24pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/9 "2025-09-21T19:24:05Z")

</div>

True, I was also not able to make a ‘boardstate’ which can be comptime handled.  
An inline switch just slows down. So I made a switch which checks:

1. are there any pins?
2. are we in check?  
And then call `gen_moves (comptime check, comptime any_pins)`.

The `update_state` of my position slows down as well.

But my main thing now is getting the engine working without any bug.  
The first version plays around 2200 ELO strength is my guess, but not bug free.  
(mainly repetition drama’s, transpositiontable misery and still a quite naive eval).

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [September 22, 2025, 9:48pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/10 "2025-09-22T21:48:20Z")

</div>

I stopped the project. Too difficult.  
Edit: I continued the project. Almost at version 1…

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [November 13, 2025, 9:55am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/11 "2025-11-13T09:55:32Z")

</div>

> **[CCRL - Index](https://computerchess.org.uk/ccrl/4040/)**

Chessnix 1.0 enters the scene with an ELO of 2842

---

<div class="post-metadata">

**Author:** ![guotie](https://ziggit.dev/user_avatar/ziggit.dev/guotie/32/6766_2.png) [@guotie](https://ziggit.dev/u/guotie)\
**Post date:** [November 13, 2025, 1:57pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/12 "2025-11-13T13:57:05Z")

</div>

so great job!

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [December 5, 2025, 9:41pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/13 "2025-12-05T21:41:51Z")

</div>

Little update: chessnix\_bot can be played on [lichess.org](http://lichess.org). It also supports Chess960.  
I rented a cheap server for it.

Soon to be expected: chessnix goes 3000 ELO

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [April 28, 2026, 7:04am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/14 "2026-04-28T07:04:25Z")

</div>

Version 1.4 released: better stronger faster.  
A kind of inbetween version, because this is the last one using zig 0.15.2

> **[Release 1.4 · ericlangedijk/chessnix](https://github.com/ericlangedijk/chessnix/releases/tag/1.4)**
>
> This will be the last version using Zig 0.15.2.
> Version 1.4
> 
> Compiler: Zig 0.15.2.
> Stronger: Optimistic estimation: ~3300 ELO (blitz ~3350).
> Added: Evaluation: knight outpost refinement, bishop on ...

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [May 8, 2026, 12:55pm UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/15 "2026-05-08T12:55:50Z")

</div>

Little update.

Above expections!  
 ![image](https://ziggit.dev/uploads/default/original/2X/5/57674014e7a195d715808d9bfa4f003a998a65bb.png)

> **[CCRL - Index](https://computerchess.org.uk/4040/)**

Next step: “the re-tuning math hell”

---

<div class="post-metadata">

**Author:** ![guotie](https://ziggit.dev/user_avatar/ziggit.dev/guotie/32/6766_2.png) [@guotie](https://ziggit.dev/u/guotie)\
**Post date:** [May 9, 2026, 9:25am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/16 "2026-05-09T09:25:34Z")

</div>

Could this repo support chinese chess?

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [May 9, 2026, 9:41am UTC](https://ziggit.dev/t/my-first-zig-chess-step/11254/17 "2026-05-09T09:41:11Z")

</div>

Definitely not. The code is very specific for classic chess and chess960. I have been thinking about supporting a plethora of chess variants, but that would take an insane amount of time.
