ChesSkelet: micro chess program - 363 Bytes

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
arkannoyed
Manic Miner
Posts: 366
Joined: Mon Feb 05, 2018 9:56 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by arkannoyed » Tue May 28, 2019 11:43 am

...or a little cheeky -1 byte

Code: Select all

	ld h,10h
loop:
	add hl,hl
	jr nc,loop
	
	sub h
	add a,b
1 x

reeagbo
Berk
Posts: 39
Joined: Mon Apr 29, 2019 8:11 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by reeagbo » Tue May 28, 2019 7:40 pm

arkannoyed wrote:
Tue May 28, 2019 11:43 am
...or a little cheeky -1 byte

Code: Select all

	ld h,10h
loop:
	add hl,hl
	jr nc,loop
	
	sub h
	add a,b
Wow! Yes, I have not tried it, but this surely works. As you say, HL is recovered so we can play with it. Never thought of H being used for this. :-)

To be tested and included in the next version. Thank you!
1 x

User avatar
arkannoyed
Manic Miner
Posts: 366
Joined: Mon Feb 05, 2018 9:56 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by arkannoyed » Wed May 29, 2019 9:01 am

Great, I thought it looked like it should fit ok. Your code is generally pretty optimised though, so it’s hard to find anything that can be improved in size.
0 x

User avatar
arkannoyed
Manic Miner
Posts: 366
Joined: Mon Feb 05, 2018 9:56 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by arkannoyed » Fri May 31, 2019 8:10 am

Just another thought, expanding upon the previous improvement in size. Would this work by extending the use of HL a bit further?

Code: Select all

; compensate + prioritize piece valuation(6B)
skiato	add a, $20		; A: 00pppppp, compensate=K+1, pih
	ld h,a

evacol	ld a, e			; A: 0rrr0ccc
	; these two values below can be tuned for different opening schemes
	if feamod>0
		add a, 2		; A: 0rrr0ccc
		and 5			; A: 00000ccc
	else
		inc a			; A: 0rrr0ccc
		and 4			; A: 00000cc0 (weight: 0,0,0,4,4,4,4,0)
	endif

; ranks weight (ranks weight is 8..1, aiming for board's end)
evarnk	add hl,hl
	add a,h			; 
	ld h,00h
	add hl,hl
	add hl,hl
	add hl,hl
	sub h			; A: 0ppppxww (x=p+r)

Saves another few bytes (I think?!) :?
1 x

reeagbo
Berk
Posts: 39
Joined: Mon Apr 29, 2019 8:11 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by reeagbo » Fri May 31, 2019 8:59 am

Chapter 6: Move list generation

As announced, here comes the last chapter of this dissection, that I´ll split in two parts. I will explain what the data used means and later, in a separate sub-chapter we´ll look into genlis code.

The idea of using static data to describe the pieces moves over the board is quite common and I'm not really doing anything different from other programs. However, I've tried to give it some more value to it. The potential moves for a piece are described in two steps, therefore we have two data blocks:

Code: Select all

org $7F88			; pawn: $22x4=$84
; piece, move type, vector list delta address (18B)
; move type / 0 / 0 / pawn straight / pawn diagonal / DDDD (real radius + 7)
movlis
pawgen 	defb 	$28, $E3	; pawn straight
	defb  	$18, $E7	; pawn capture
org $7F8C
knigen	defb	$08, $EA	;
org $7F90
bisgen	defb	$0E, $E5	; bishop
org $7F94
roogen	defb 	$0E, $E0	; rook
org $7F9C
quegen	defb	$0E, $E0	; queen
	defb	$0E, $E5	;
org $7FD8
kingen	defb	$08, $E0	; king: $($16+$20)x4=$D8
	defb	$08, $E5	;
The data in this first block is strategically placed in memory. The info corresponding to each piece sits in the piece value multiplied by 4. Take into account that we are only creating the move list for white pieces (i.e. white bishop value is 24h, 24h x 4= 90h). This allows me to address quite immediately the type of moves every piece can make. What do these two bytes mean?
  • Byte1: The first byte indicates the type of move the piece makes. It contains 2 pieces of information: in the low nibble we have what I call the radius. A Knight or the King have radius=1, and a Bishop, Queen or Rook have a radius=7. This is how far they can reach when moving in a direction. This value is used to control the loop when the code tries to move the piece in one particular direction. That was the original value. Later I increased that by 7 so that when I decrease it I can detect the 0 by looking at bit 3 of this radius. This helps saving some code.

    Also, the values produced by adding this delta to the current square are aligned to the 0x88 (we saw this some time ago) code to detect pieces going out of the board.

    The higher nibble contains what I call special moves info. These are specific flags in bit4 and bit5 indicating the special Pawn moves. Take into account that a Pawn behavior is not regular: it cannot capture when moving straight and can only move diagonally when capturing, and these are not standard behaviors, so the code needs to know about it, and it's easier to provide this information directly to the code, instead of the code having to derive it from knowing that we have a Pawn moving this way or the other.
  • Byte2: The second byte is just a pointer to the move vectors that we´ll see below. Again, note that these two blocks of data are placed in the same micro page in RAM, so H does not need to be altered during this process.

Code: Select all

org $7FE0			; vectors start at: $7FE0 (arbitrary)
; (y, x) move delta pairs (16B)
veclis
strvec 	defb   	$FF, $01	; +0, straight vectors
	defb   	$10, $F0	; +3, straight pawn, last half line
org $7FE5
diavec	defb   	$0F, $11	; +5, diagonal vectors
	defb  	$EF, $F1	; +7, diagonal pawn
org $7FEA
knivec	defb 	$E1, $F2	; +10, knight vectors
	defb  	$12, $21	; knight moves listed clockwise
	defb  	$1F, $0E	;
	defb  	$EE, $DF	;
The second data block contains generic move descriptions, not specific to a piece, therefore a move descriptor can be used by several piece types. There are three groups: first 4 bytes describe the straight moves, second 4 bytes describe diagonal moves, and the last 8 bytes describe the Knight moves.

Each byte in these blocks indicates how many bytes we need to displace from the current piece square (byte) to reach the target square. If you remember, we've been discussing the board as a 16x8 byte space. Actually, that space is a linear array of bytes. Using the King example, to move it to the right we just add 1 to the current square, to move it left we subtract 1 to the current square. What may be less obvious is that to move it one rank ahead we just need to subtract 16 to the current square (remember, each rank is made of 16 bytes, 8 used and 8 unused), which is actually a very simple operation. Same idea applies to diagonal and Knight moves.

This is what each byte means. How do we reach the right blocks for each piece?

Let me illustrate it with some examples:
  • the Rook pointer in the first data block (E0h) will only point at the first group in this second block for straight moves. As the Rook has a its own radius 7 (0Eh with the delta=7) everything will be fine.
  • the King will point at this same group as the Rook (E0h), but also at the second group (E5h) for diagonal moves. The difference with the Rook is that radius for the king is 1 (08h).
  • the nice thing about this arrangements is that Pawn moves (only one direction) can be found too as part of the straight (E3h) and diagonal move (E7h) blocks too. So we do not need additional descriptors for them.
Now that now the used of this static data, we´ll see in the very last chapter how the code uses it and how the potential move list is built.
2 x

User avatar
arkannoyed
Manic Miner
Posts: 366
Joined: Mon Feb 05, 2018 9:56 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by arkannoyed » Fri May 31, 2019 11:11 am

Very good. I'm along the same lines with moves data, but mine is currently slightly bigger data. Good system that works pretty well though.
0 x

reeagbo
Berk
Posts: 39
Joined: Mon Apr 29, 2019 8:11 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by reeagbo » Fri May 31, 2019 9:59 pm

arkannoyed wrote:
Fri May 31, 2019 8:10 am
Just another thought, expanding upon the previous improvement in size. Would this work by extending the use of HL a bit further?

Code: Select all

; compensate + prioritize piece valuation(6B)
skiato	add a, $20		; A: 00pppppp, compensate=K+1, pih
	ld h,a

evacol	ld a, e			; A: 0rrr0ccc
	; these two values below can be tuned for different opening schemes
	if feamod>0
		add a, 2		; A: 0rrr0ccc
		and 5			; A: 00000ccc
	else
		inc a			; A: 0rrr0ccc
		and 4			; A: 00000cc0 (weight: 0,0,0,4,4,4,4,0)
	endif

; ranks weight (ranks weight is 8..1, aiming for board's end)
evarnk	add hl,hl
	add a,h			; 
	ld h,00h
	add hl,hl
	add hl,hl
	add hl,hl
	sub h			; A: 0ppppxww (x=p+r)

Saves another few bytes (I think?!) :?
Let me look into it. I'll let you know. Any help is more than welcome. :-)
1 x

reeagbo
Berk
Posts: 39
Joined: Mon Apr 29, 2019 8:11 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by reeagbo » Sun Jun 02, 2019 9:51 am

reeagbo wrote:
Fri May 31, 2019 9:59 pm
arkannoyed wrote:
Fri May 31, 2019 8:10 am
Just another thought, expanding upon the previous improvement in size. Would this work by extending the use of HL a bit further?

Code: Select all

; compensate + prioritize piece valuation(6B)
skiato	add a, $20		; A: 00pppppp, compensate=K+1, pih
	ld h,a

evacol	ld a, e			; A: 0rrr0ccc
	; these two values below can be tuned for different opening schemes
	if feamod>0
		add a, 2		; A: 0rrr0ccc
		and 5			; A: 00000ccc
	else
		inc a			; A: 0rrr0ccc
		and 4			; A: 00000cc0 (weight: 0,0,0,4,4,4,4,0)
	endif

; ranks weight (ranks weight is 8..1, aiming for board's end)
evarnk	add hl,hl
	add a,h			; 
	ld h,00h
	add hl,hl
	add hl,hl
	add hl,hl
	sub h			; A: 0ppppxww (x=p+r)

Saves another few bytes (I think?!) :?
Let me look into it. I'll let you know. Any help is more than welcome. :-)
I took your idea and with a little tuning it seems to make things even smaller:

Code: Select all

	; compensate + prioritize piece valuation(6B)
skiato	ld h, $20		; prepare H for later rotation and use for A
	add a, h		; A: 00pppppp, compensate=K+1, pih				      					       
	rlca			; leave space for square weight
	rlca			; A: pppppp00, piece addition is 5 bits
	ld b, a			; B: piece addition value
evacol	ld a, e			; A: 0rrr0ccc
	; these two values below can be tuned for different opening schemes
	if feamod>0
		add a, 2		; A: 0rrr0ccc
		and 5			; A: 00000ccc
	else
		inc a			; A: 0rrr0ccc
		and 4			; A: 00000cc0 (weight: 0,0,0,4,4,4,4,0)
	endif

	; ranks weight (ranks weight is 8..1, aiming for board's end)
evarnk	add hl, hl		; HL: 00100000 0rrr0ccc (before)
	add hl, hl		; 
	add hl, hl		; HL: 000000rr r0ccc000 (after)
	sub h			; A:  00000cww (w=r+c)
	add a, b		; total value: pieces + weight
Many thanks! This is from now on the arkannoyed patch! :-)
1 x

reeagbo
Berk
Posts: 39
Joined: Mon Apr 29, 2019 8:11 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by reeagbo » Sun Jun 02, 2019 9:53 am

Maybe we can still cross the 350 bytes line! :P
1 x

reeagbo
Berk
Posts: 39
Joined: Mon Apr 29, 2019 8:11 am

Re: ChesSkelet: micro chess program - 363 Bytes

Post by reeagbo » Sun Jun 02, 2019 9:55 am

Maybe we can still cross the 350 bytes line! :P

One general question. I´m sure some of the folks in the forum can help: how do I get ChesSkelet included in ZXDB?
0 x

Post Reply