Assembly seems overkill though.
I believe most of the 8bit microcontrollers from this era have no good optimizing compilers that get close to what competent practitioners achieve with assembly. I think it has to do with having complex addressing modes making the C stack fairly inefficient.
For an 8 bit Z80 based hardware project like this, assembly is a valid choice. The reason is performance. You'll lose significant performance with a compiler or interpreter.
The quickest way to redraw a screen or otherwise copy a memory region on Spectrum of is to use POP/PUSH instructions while flipping the stack pointer. Good luck getting that with C.
assembly is the only choice. The Z80 processor is a twisty collection of registers, none alike. It is pretty much the opposite of what a, for example, C compiler is looking for.
In fact C compilers are _notoriously_ bad at producing code for the Z80.
There is practically no other choice on a Z80. C compilers really don't like the Z80 ISA and create both slow and bloated output, at least compared to manually written asm. And on top, you can do many optimization tricks in assembly that simply are not possible in a high level language (self-modifying code, jumping into the middle of an instruction, etc...).
Forth might work better than C, but tbh, assembly code is more straightforward and easier to read than Forth ;)