+TheBF Posted December 9, 2020 Share Posted December 9, 2020 13 minutes ago, dhe said: Bump Bumpedy Bump Bump ... Bump Bump. I hit a wall with comprehension of the code and went on to native code generation, a slightly less brain numbing exercise. Thanks for the reminder. Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-4695670 Share on other sites More sharing options...
+Vorticon Posted December 10, 2020 Author Share Posted December 10, 2020 I took a break from this project a couple of months ago as I kept hitting a wall with the evaluation function and the computer play was laughable. I may have to rethink a few algorithms... 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-4696090 Share on other sites More sharing options...
zbyti Posted December 12, 2020 Share Posted December 12, 2020 On 12/10/2020 at 2:08 PM, Vorticon said: I took a break from this project a couple of months ago as I kept hitting a wall with the evaluation function and the computer play was laughable. I may have to rethink a few algorithms... Don't give up! :] 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-4698053 Share on other sites More sharing options...
+Vorticon Posted November 4 Author Share Posted November 4 After a very long hiatus (per my notes I started this project on 3/14/2015), I've decided to take a fresh look at it, starting by scrapping my entire existing code base and re-thinking my approach. My initial attempt was a brute force method, coupled with a very primitive evaluation function and no assembly support, resulting in what is essentially an unplayable chess engine. I'm still far from certain that the end result will be any better, but we shall see! I am still coding this in UCSD Pascal, but this time around I will be using assembly language support routine for time-critical parts as I am now far more proficient in UCSD Pascal than I was nearly 10 years ago. So first focus is going to be on improving the speed and efficiency of move generation. This is usually a very time consuming and involved process where the computer will test the movement potential of each piece on the board in order to prep for move evaluation. After doing some research, I was very seduced by the idea of using bitboards to represent the playing board. Bitboards are essentially 64-bit numbers representing the 64 board positions, which can be manipulated with logical operations (NOT, OR, AND, XOR, RSHIFT, LSHIFT) in various ways to quickly determine valid moves, captures etc... This is a rather involved process, but this excellent link will clearly explain the underlying concepts: https://pages.cs.wisc.edu/~psilord/blog/data/chess-pages/index.html Now there is an obvious problem here, which is that our humble TI cannot handle 64-bit integers, but it can natively handle 16-bit ones, so all I had to do was break up the bitboard into 4 16-bit sections represented by an a 4-dimension integer array like so: type bitboard = array[0..3] of integer; var bit : bitboard; Obviously this does slow things down a bit, but I believe the gains in efficiency will more than make up for this. Having decided on bitboards, I now needed to come up with routines to perform the necessary logical operations mentioned above in assembly. The source listings below show the bitboard operations module in assembly and the bittest program to verify functionality: Spoiler ;bitboard logical operations routines ;bitboard is an array[0..3] of integer .proc bitnot,2 ;complements a bitboard ;usage: bitnot(var bitboard1[0], bitboard2[0]) ;the complement of bitboard1 will be stored in bitboard2 .def procret mov r11,@procret mov *r10+,r6 ;get pointer to bitboard2 mov *r10,r5 ;get pointer to bitboard1 mov *r5+,r4 ;protect content of bitboard1 inv r4 ;complement bitboard1 mov r4,*r6+ ;store in bitboard2 mov *r5+,r4 inv r4 mov r4,*r6+ mov *r5+,r4 inv r4 mov r4,*r6+ mov *r5,r4 inv r4 mov r4,*r6 mov @procret,r11 b *r11 procret .word .proc bitand,3 ;logically AND 2 bitboards ;usage: bitand(var bitboard1, bitboard2, bitboard3) ;bitboard1 and bitboard2 are ANDed and the result placed in bitboard3 .ref procret mov r11,@procret mov *r10+,r7 ;get pointer to bitboard3 mov *r10+,r6 ;get pointer to bitboard2 mov *r10,r5 ;get pointer to bitboard1 mov *r5+,r3 ;protect contents of bitboard1 and bitboard2 mov *r6+,r4 inv r3 ;AND bitboard1 with bitboard 2 szc r3,r4 ;inv then szc = and mov r4,*r7+ ;save result in bitboard3 mov *r5+,r3 mov *r6+,r4 inv r3 szc r3,r4 mov r4,*r7+ mov *r5+,r3 mov *r6+,r4 inv r3 szc r3,r4 mov r4,*r7+ mov *r5,r3 mov *r6,r4 inv r3 szc r3,r4 mov r4,*r7 mov @procret,r11 b *r11 .proc bitor,3 ;logicaly OR two bitboards ;usage: bitor(bitboard1, bitboard2, bitboard3) ;bitboard1 and bitboard2 are ORed and the result placed in bitboard3 .ref procret mov r11,@procret mov *r10+,r7 ;get pointer to bitboard3 mov *r10+,r6 ;get pointer to bitboard2 mov *r10,r5 ;get pointer to bitboard1 mov *r6+,r3 ;protect contents of bitboard2 soc *r5+,r3 ;or bitboard1 and bitboard2 mov r3,*r7+ ;store result in bitboard3 mov *r6+,r3 soc *r5+,r3 mov r3,*r7+ mov *r6+,r3 soc *r5+,r3 mov r3,*r7+ mov *r6,r3 soc *r5,r3 mov r3,*r7 mov @procret,r11 b *r11 .proc bitxor,3 ;logically XOR two bitboards ;usage: bitxor(var bitboard1, bitboard2, bitboard3) ;bitboard1 and bitboard2 are XORed and the result placed in bitboard3 .ref procret mov r11,@procret mov *r10+,r7 ;get pointer to bitboard3 mov *r10+,r6 ;get pointer to bitboard2 mov *r10,r5 ;get pointer to bitboard1 mov *r6+,r4 ;xor bitboard1 and bitboard2 xor *r5+,r4 mov r4,*r7+ ;store result in bitboard3 mov *r6+,r4 xor *r5+,r4 mov r4,*r7+ mov *r6+,r4 xor *r5+,r4 mov r4,*r7+ mov *r6,r4 xor *r5,r4 mov r4,*r7 mov @procret,r11 b *r11 .proc rshift,3 ;logically right shift a bitboard ;usage: rshift(var bitboard1, bitboard2; intnum) ;bitboard1 is logically right shifted intnum times ;the result is placed in bitboard2 .ref procret mov r11,@procret mov *r10+,r5 ;get number of shifts mov *r10+,r7 ;get pointer to bitboard2 mov *r10,r6 ;get pointer to bitboard1 mov *r6+,r1 ;transfer bitboard1 to regs 1-4 mov *r6+,r2 mov *r6+,r3 mov *r6,r4 nxtshft srl r4,1 ;right shift r4-r1 sequentially 1 position srl r3,1 jnc notset1 ;transfer carry bit to next register if set ori r4,8000h notset1 srl r2,1 jnc notset2 ori r3,8000h notset2 srl r1,1 jnc notset3 ori r2,8000h notset3 dec r5 ;done with shifts? jne nxtshft mov r1,*r7+ ;save shifted bitboard1 to bitboard2 mov r2,*r7+ mov r3,*r7+ mov r4,*r7 mov @procret,r11 b *r11 .proc lshift,3 ;logically left shift a bitboard ;usage: lshift(var bitboard1, bitboard2; intnum) ;bitboard1 is logically left shifted intnum times ;the result is placed in bitboard2 .ref procret mov r11,@procret mov *r10+,r5 ;get number of shifts mov *r10+,r7 ;get pointer to bitboard2 mov *r10,r6 ;get pointer to bitboard1 mov *r6+,r1 ;transfer bitboard1 to r1-r4 mov *r6+,r2 mov *r6+,r3 mov *r6,r4 newshft sla r1,1 ;left shift r1-r4 in sequence 1 position sla r2,1 jnc nocar1 ;transfer carry bit to previous register if set ori r1,0001h nocar1 sla r3,1 jnc nocar2 ori r2,0001h nocar2 sla r4,1 jnc nocar3 ori r3,0001h nocar3 dec r5 ;done with shifts? jne newshft mov r1,*r7+ ;save shifted bitboard1 to bitboard2 mov r2,*r7+ mov r3,*r7+ mov r4,*r7 mov @procret,r11 b *r11 .end Spoiler {test program for bitboard manipulation} program bittest; type bitboard = array[0..3] of integer; var bit1, bit2, bitres : bitboard; i : integer; procedure bitnot(var b1, br : integer); external; procedure bitand(var b1, b2, br : integer); external; procedure bitor(var b1, b2, br : integer); external; procedure bitxor(var b1, b2, br : integer); external; procedure rshift(var b1, br: integer; n : integer); external; procedure lshift(var b1, br: integer; n : integer); external; procedure bitdisp(var bitres : bitboard; n : integer); {if n = 1 then bitboard display is shifted by 12 columns} type byte = 0..255; dual = record case boolean of true : (value : integer); false : (bytes : packed array[0..1] of byte); end; var i, j, k, y, bitpos : integer; bitval : dual; begin bitpos := 256; y := 0; if n = 1 then begin y := 3; gotoxy(11, y); end; for i := 0 to 3 do begin bitval.value := bitres[i]; for j := 0 to 1 do begin for k := 0 to 7 do begin bitpos := bitpos div 2; if ord (odd(bitval.bytes[j]) and odd(bitpos)) <> 0 then write('1') else write('0'); end; y := succ(y); if n = 1 then gotoxy(11, y) else writeln; bitpos := 256; end; end; end; (* bitdisp *) begin page(output); {test NOT functionality} for i := 0 to 3 do bit1[i] := 0; writeln('testing NOT functionality'); writeln; writeln('initial bitboard:'); bitdisp(bit1, 0); writeln; bitnot(bit1[0], bitres[0]); writeln('after NOT operation:'); bitdisp(bitres, 0); readln; page(output); {test AND functionality} writeln('testing AND functionality'); for i := 0 to 3 do begin bit1[i] := -1; bit2[i] := 0; end; writeln; writeln('initial bitboards:'); bitdisp(bit1, 0); bitdisp(bit2, 1); bitand(bit1[0], bit2[0], bitres[0]); writeln; writeln('after AND operation:'); bitdisp(bitres, 0); readln; page(output); {test OR functionality} writeln('testing OR functionality'); writeln; for i := 0 to 3 do begin bit1[i] := -1; bit2[i] := 0; end; writeln('initial bitboards:'); bitdisp(bit1, 0); bitdisp(bit2, 1); writeln; bitor(bit1[0], bit2[0], bitres[0]); writeln('after OR operation:'); bitdisp(bitres, 0); readln; page(output); {test XOR functionality} writeln('testing XOR functionality'); writeln; for i := 0 to 3 do begin bit1[i] :=-1; bit2[i] := 0; end; writeln('initial bitboards:'); bitdisp(bit1, 0); bitdisp(bit2, 1); writeln; bitxor(bit1[0], bit2[0], bitres[0]); writeln('after XOR operation:'); bitdisp(bitres, 0); readln; page(output); {test right shift functionality} writeln('testing right shift functionality'); writeln; for i := 0 to 3 do bit1[i] := -1; writeln('initial bitboard:'); bitdisp(bit1, 0); writeln; rshift(bit1[0], bitres[0], 9); writeln('after right shift 9:'); bitdisp(bitres, 0); readln; page(output); {test left shift functionality} writeln('testing left shift functionality'); writeln; for i:=0 to 3 do bit1[i] := -1; writeln('initial bitboard'); bitdisp(bit1, 0); writeln; lshift(bit1[0], bitres[0], 9); writeln('after left shift 9'); bitdisp(bitres, 0); readln; page(output); end. bittest.mp4 So that seems to work quite well. I should mention that while displaying the bitboards is slow, the operations themselves are very fast. The next issue related to bitboards is that many bitboards will need to be generated and stored in order to properly represent the state of the game, so I will likely need to leverage the SAMS card for this. Luckily I did develop a SAMS module for UCSD Pascal previously (see the Pascal thread), so that should help. More to come 7 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5560178 Share on other sites More sharing options...
+TheBF Posted November 4 Share Posted November 4 Maybe you could just shoe-horn a small LLM into SAMS and let it learn by itself. You do some very neat things with this old machine, I must say. 2 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5560281 Share on other sites More sharing options...
+Vorticon Posted November 4 Author Share Posted November 4 2 minutes ago, TheBF said: Maybe you could just shoe-horn a small LLM into SAMS and let it learn by itself. You do some very neat things with this old machine, I must say. That's where the fun is! I have actually mulled over the idea of creating a machine learning algorithm to have the TI teach itself chess, but only very superficially, and I suspect that would require pretty large memory space where even a 1MB SAMS might not be enough. Once my move generator is complete, it might be something worth re-visiting. The key here would be to have a good evaluation function to start with. My overall goal for this project is to eventually have a chess engine that could beat Video Chess 100% of the time at its highest level. We'll see how far I get... 3 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5560289 Share on other sites More sharing options...
+Vorticon Posted November 11 Author Share Posted November 11 I've finished the initialization program which generates the 112 base bitboards (896 bytes) for the game and which will run ahead of the main program. These bitboards will be used to generate many more bitboards on the fly as the game progresses for move generation, attack tables etc... using the logical operators discussed earlier. All these tables reside in the SAMS card, and below is a test program which generates the baseboards, saves them to the SAMS, then reads them back and displays them. The rendering is slow but the underlying bitboard operations are pretty speedy. Bitboard Generation.mp4 7 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5564022 Share on other sites More sharing options...
+Vorticon Posted November 21 Author Share Posted November 21 OK the base bitboards generation is now complete, including pre-generated movement squares for each type of piece of every board square, i.e. 64 bitboards per piece. The whole thing takes about 1 minute to complete and occupies 4.5K of SAMS space (full page and 512 bytes of subsequent page). I plan to allocate 512K for a hash table and 256K for an opening library, targeting a 1M SAMS card. I am essentially trading memory for efficiency and speed. This is what the SAMS card was born to do Next is coming up with a good evaluation function, the hardest aspect of chess engine programming. How does one approximate the intuitive thinking of a human? Lots of research ahead... Bitboard Generation.mp4 6 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569304 Share on other sites More sharing options...
Gary from OPA Posted November 21 Share Posted November 21 Now all it needs is a nice "Phoenix" logo.. 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569353 Share on other sites More sharing options...
+Vorticon Posted November 21 Author Share Posted November 21 6 hours ago, Gary from OPA said: Now all it needs is a nice "Phoenix" logo.. Let's first make sure I end up with a playable engine! Too early to tell 2 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569437 Share on other sites More sharing options...
apersson850 Posted November 21 Share Posted November 21 You are aware of that if you have to integers, a and b, the inversion of a will end up in b if you do b := ord(not(odd(a))); Lines like c := ord(odd(a) and odd(b)); are also allowed. You should also be aware of the moveleft, moveright and fillchar intrinsics availalbe in Pascal. There's also scan that may be useful. Doing your own assembly is of course good too, and can be even faster, but these commands may make it possible to test things on Pascal level without sacrificing too much speed. Explanation: In UCSD Pascal, the function odd does nothing more than return the state of the least significant bit and allow you to treat the operator as a logical value. In a similar way, the function ord applied to a logical value does nothing more than allow you to treat it as an integer. In neither case are the values themselves changed. 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569486 Share on other sites More sharing options...
+TheBF Posted November 21 Share Posted November 21 11 hours ago, Vorticon said: I plan to allocate 512K for a hash table and 256K for an opening library, targeting a 1M SAMS card. I don't know what your hashing method will be but text books say making the size of the hash table a prime number will reduce collisions. 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569518 Share on other sites More sharing options...
+Vorticon Posted November 21 Author Share Posted November 21 3 hours ago, TheBF said: I don't know what your hashing method will be but text books say making the size of the hash table a prime number will reduce collisions. I only have a high level concept of the move hash tables at this point but I did come across that. Priority for now is to design the evaluation function and search algorithms. The hash tables' impact will really be on efficiency of search but not on quality of play, so they are on a lower priority. Baby steps 3 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569632 Share on other sites More sharing options...
+Vorticon Posted November 21 Author Share Posted November 21 4 hours ago, apersson850 said: You are aware of that if you have to integers, a and b, the inversion of a will end up in b if you do b := ord(not(odd(a))); Lines like c := ord(odd(a) and odd(b)); are also allowed. You should also be aware of the moveleft, moveright and fillchar intrinsics availalbe in Pascal. There's also scan that may be useful. Doing your own assembly is of course good too, and can be even faster, but these commands may make it possible to test things on Pascal level without sacrificing too much speed. Explanation: In UCSD Pascal, the function odd does nothing more than return the state of the least significant bit and allow you to treat the operator as a logical value. In a similar way, the function ord applied to a logical value does nothing more than allow you to treat it as an integer. In neither case are the values themselves changed. Yup I use ORD in my bitboard display function that way. Strange way of doing things but it works. There is a good explanation in the Advanced UCSD Pascal Programming book. 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5569635 Share on other sites More sharing options...
apersson850 Posted November 24 Share Posted November 24 It was invented due to the desire to be able to use UCSD Pascal as a language to write an operating system with. That requires some special functions, like bitwise logical operations, things they wanted to include into the language without modifying it more than necessary. 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5571220 Share on other sites More sharing options...
+Vorticon Posted November 28 Author Share Posted November 28 As I was working on the move generation algorithm, I came across a thorny problem: With bitboards, generating movement lists is relatively easy. Retrieve the pre-generated movement bitboard for the piece of interest on the square it is on, XOR it with the automatically maintained bitboard of all the pieces of the same color, and the result is a bitboard with all the legal squares that piece can move to, including captures. However, with the sliding pieces (rook, bishop and queen) it's not quite so simple. For example, below is the movement bitboard for a queen in the middle of the board: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Q 1 1 1 1 1 1 1 1 1 1 1 1 1 Here is the bitboard of all the pieces of the same color (blocking pieces) 1 1 1 1 XORing these 2 bitboards together gives us this bitboard: 1 1 1 1 1 1 1 1 1 1 1 1 Q 1 1 1 1 1 1 1 1 1 1 1 You can immediately see that the movement rays continue beyond where the blocking pieces were unless they are on the edge of the board, and that was definitely not trivial to fix. While there was a way to do this in straight Pascal, it was way too slow and I ended up coding a ray trimming routine in assembly. One of the difficulties was due to the fact that a bitboard is represented by an array of 4 words, and it was necessary to be able to figure out which byte and offset to that byte a particular bit of interest was located across the entire array. Luckily this was not too dissimilar to accessing the individual pixels on the bitmap screen, which I had ample experience with previously, so that helped. Here's what the final movement bitboard would look like in this case: 1 1 1 1 1 1 1 1 1 Q 1 1 1 1 1 1 1 1 1 1 Regardless, it is not hard to see how useful and efficient bitboards are in chess... 4 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5574597 Share on other sites More sharing options...
+Vorticon Posted November 30 Author Share Posted November 30 Preliminary move generation test: the program can generate all the legal moves for all the pieces on both sides (2 ply or 1 turn) in 4.25 seconds. Not bad... Mind you this is likely to get (much) longer once we add an evaluation function into the mix and we go deeper into the search tree, but it's an encouraging result which is already significantly faster than the miserable original iteration of this project. I'm attaching the disk image in case someone wants to browse the source files, but it's probably going to be difficult to follow at this stage. PHOENIX.dsk 3 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5575852 Share on other sites More sharing options...
+TheBF Posted December 1 Share Posted December 1 I was thinking of your work with bit tables and I remembered I found this thing in Forth to find the first bit. Maybe it would be useful, if you coded it up in Assembler. ?? ?? \ sourec: https://forth.sourceforge.net/algorithm/firstbit/index.html \ explanation: \ sourec: https://forth.sourceforge.net/algorithm/firstbit/index.html \ Let us consider the 1st set bit. \ On the first step, DUP 1 RSHIFT OR, it gets copied to the bit that follows it. \ On the 2nd step, it gets copies to the two bits that follow the two bits mentioned on the previous step. \ And so on. Finally, all bits below the first set bit become set. \ Then, 1 RSHIFT XOR clears all set bits except the very 1st one. DECIMAL : FIRSTBIT ( number -- firstbit ) DUP 1 RSHIFT OR DUP 2 RSHIFT OR DUP 4 RSHIFT OR DUP 8 RSHIFT OR DUP 16 RSHIFT OR DUP 1 RSHIFT XOR ; 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5575933 Share on other sites More sharing options...
+Vorticon Posted December 1 Author Share Posted December 1 4 hours ago, TheBF said: I was thinking of your work with bit tables and I remembered I found this thing in Forth to find the first bit. Maybe it would be useful, if you coded it up in Assembler. ?? ?? \ sourec: https://forth.sourceforge.net/algorithm/firstbit/index.html \ explanation: \ sourec: https://forth.sourceforge.net/algorithm/firstbit/index.html \ Let us consider the 1st set bit. \ On the first step, DUP 1 RSHIFT OR, it gets copied to the bit that follows it. \ On the 2nd step, it gets copies to the two bits that follow the two bits mentioned on the previous step. \ And so on. Finally, all bits below the first set bit become set. \ Then, 1 RSHIFT XOR clears all set bits except the very 1st one. DECIMAL : FIRSTBIT ( number -- firstbit ) DUP 1 RSHIFT OR DUP 2 RSHIFT OR DUP 4 RSHIFT OR DUP 8 RSHIFT OR DUP 16 RSHIFT OR DUP 1 RSHIFT XOR ; Interesting. The way I implemented my bit search routine is as below, with the understanding that a bitboard is 8 bytes with the LSB of byte 7 being position 63 (right uppermost square on chess board) and MSB of byte 0 being position 0 (lower leftmost square): ;bitboard is at location bitbrd1 ;r5 has loc, the position of desired bit in bitboard (0..63) bittab .byte 128,64,32,16,8,4,2,1 ;bit mask table bitbrd1 .block 8 bitchk mov r11,@subrtn2 clr r7 ;clear index to bittab mov r5,r6 ;save loc value srl r5,3 ;calculate byte displacement (loc DIV 8) mov r5,r4 ;save byte displacement sla r5,3 ;byte displacement * 8 = clean byte boundary nxtbit c r5,r6 ;are we at loc? jeq fndbit inc r5 ;add a bit to the byte inc r7 ;advance bit mask table index jmp nxtbit fndbit ai r4,bitbrd1 ;point to displacement byte in bitboard clr r5 movb *r4,r5 ;get content of byte clr r6 movb @bittab(r7),r6 ;select appropriate bitmask inv r6 ;AND bit mask with displacement byte (INV then SZCB) szcb r6,r5 ;high byte of r5 has value of displacement bit. ;a byte compare to 0 will indicate if bit is set or reset mov @subrtn2,r11 b *r11 Now your suggestion gave me an idea that is efficient and does not need assembly! In Pascal, I would select the bitboard representing the desired square to be checked (loc) and AND it with the bitboard I need to check, resulting in a cleared bitboard that preserves the value of the bit at loc. RSHIFT that bitboard 63-loc and read the value of the last byte in the bitboard, either a 0 or 1. (Technically though this is not pure Pascal since the logical bitboard ops are implemented in assembly ) For example, if we have that bitboard: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 And we are interested in that particular bit (loc = 34) - There is a pre-generated bitboard for each square on the chess board 1 ANDing the two boards yields this: 1 Finally RSHIFT 63-34 = 29 and we get 1 So the least significant bit in the last byte of the bitboard now has the state of the loc bit. 3 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576056 Share on other sites More sharing options...
apersson850 Posted December 1 Share Posted December 1 13 hours ago, Vorticon said: ;bitboard is at location bitbrd1 ;r5 has loc, the position of desired bit in bitboard (0..63) bittab .byte 128,64,32,16,8,4,2,1 ;bit mask table bitbrd1 .block 8 bitchk mov r11,@subrtn2 NOT NEEDED, SINCE THERE'S NO BL IN THIS PROCEDURE clr r7 ;clear index to bittab mov r5,r6 ;save loc value srl r5,3 ;calculate byte displacement (loc DIV 8) mov r5,r4 ;save byte displacement sla r5,3 ;byte displacement * 8 = clean byte boundary nxtbit c r5,r6 ;are we at loc? jeq fndbit inc r5 ;add a bit to the byte inc r7 ;advance bit mask table index jmp nxtbit fndbit ai r4,bitbrd1 ;point to displacement byte in bitboard YOU CAN SKIP THIS INSTRUCTION clr r5 movb *r4,r5 ;get content of byte USE MOVB @BITBRD1(R4),R5 clr r6 movb @bittab(r7),r6 ;select appropriate bitmask inv r6 ;AND bit mask with displacement byte (INV then SZCB) szcb r6,r5 ;high byte of r5 has value of displacement bit. ;a byte compare to 0 will indicate if bit is set or reset mov @subrtn2,r11 NOT NEEDED, SINCE THERE'S NO BL IN THIS PROCEDURE b *r11 I had a look at that code. I entered some suggestions in CAPITAL letters. It will save you a few clock cycles, unless there's more going on around that procedure that requires your instructions to be there. 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576320 Share on other sites More sharing options...
Gary from OPA Posted December 1 Share Posted December 1 Nanochess (author of CVBasic) has done an amazing chess game in x86 and JavaScript. The AI is not bad. I wonder if some of his AI logic could be adapted to your Pascal chess. 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576364 Share on other sites More sharing options...
+Vorticon Posted December 2 Author Share Posted December 2 6 hours ago, apersson850 said: I had a look at that code. I entered some suggestions in CAPITAL letters. It will save you a few clock cycles, unless there's more going on around that procedure that requires your instructions to be there. Thanks! This routine is actually a subroutine for another assembly subroutine, so saving and restoring R11 is necessary. Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576595 Share on other sites More sharing options...
+Vorticon Posted December 2 Author Share Posted December 2 5 hours ago, Gary from OPA said: Nanochess (author of CVBasic) has done an amazing chess game in x86 and JavaScript. The AI is not bad. I wonder if some of his AI logic could be adapted to your Pascal chess. Yes I've seen that and it's an incredible achievement. Understanding what's going on under the hood there is another matter entirely however, and probably well above my pay grade. 1 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576600 Share on other sites More sharing options...
+Lee Stewart Posted December 2 Share Posted December 2 40 minutes ago, Vorticon said: Thanks! This routine is actually a subroutine for another assembly subroutine, so saving and restoring R11 is necessary. Not so. @apersson850 is correct. You are not changing R11 in that subroutine, so it is redundant and wasteful to save/restore it. ...lee 2 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576622 Share on other sites More sharing options...
+Vorticon Posted December 2 Author Share Posted December 2 12 hours ago, Lee Stewart said: Not so. @apersson850 is correct. You are not changing R11 in that subroutine, so it is redundant and wasteful to save/restore it. ...lee Ah I see it now since it's the last subroutine level called. I'll make change. Every saved cycle counts! Thanks. 4 Quote Link to comment https://forums.atariage.com/topic/248429-new-game-project-phoenix-chess/page/3/#findComment-5576864 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.