curiouslearn
2021-1-17 11:15:23

@badkins can you please comment on ways in which you found Racket to be better suited for this task (of chess engine) compared to Julia? I am very new to Racket. I know Julia somewhat better, but not an expert. Just curious. Thanks.


laurent.orseau
2021-1-17 11:33:33

I think what @notjack says is that you will still have a pointer to a value, and not an immediate value, because untyped (I don’t know what TR does though). The unsafe part refers to whether you’re actually handling a vector, and maybe whether you are within its boundaries


laurent.orseau
2021-1-17 11:35:06

That is, no contract checking


pihentagy
2021-1-17 12:34:24

Still playing with <https://adventofcode.com/2020/day/3|Day 3 of advent of code> I have a function to advance to the next position, and I guess I’ll have an accumulator to count the number of trees. I’d like a functional solution. How can I define an infinite sequence for that to use for a for like sequence (maybe for/list?) to solve it?


anything
2021-1-17 14:12:10

&gt; (for/list ([n (in-naturals)]) #:break (= n 10) n) '(0 1 2 3 4 5 6 7 8 9) I’m not sure if I know what you’re asking for. But there you have an infinite stream produced by (in-naturals). I’m breaking the for loop once I reach the tenth element, just so it can terminate. Is this what you’re looking for?


pihentagy
2021-1-17 14:44:38

Exactly. Oh, nice, I can build up an infinite stream by having an origin and a stepping function. I can feed for/list with that infinite sequence and accumulate the number of trees.


badkins
2021-1-17 17:14:16

I just beat it on w/ ply 8 :( although it got stuck when my pawn got to the 8th rank. It handles promotions when it’s moving, but I forgot the code to promote when entering human moves. It played decently, but I’m surprised I won at ply 8 even w/o fancy additions:


badkins
2021-1-17 17:14:19
  1. d4 c5 2. dxc5 Qa5+ 3. Nc3 Qxc5 4. Nf3 f5 5. e4 fxe4 6. Nxe4 Qb6 7. Qd4 Qxd4 8. Nxd4 d5 9. Ng3 Nc6 10. Nb5 Kd7 11. Bd3 a6 12. Nc3 e6 13. O-O Rb8 14. a3 Ra8 15. Re1 Rb8 16. Bf4 Bd6 17. Bxd6 Kxd6 18. Nce2 Ra8 19. Rad1 Nf6 20. c4 dxc4 21. Bxc4+ Ke7 22. Nc3 Rb8 23. Nf5+ Kf8 24. Bxe6 Bxe6 25. Rxe6 Re8 26. Rxe8+ Kxe8 27. Nd6+ Kf8 28. Nxb7 Ke7 29. Nc5 Re8 30. Re1+ Kf8 31. Rxe8+ Kxe8 32. Nxa6 Kf8 33. b4 Kg8 34. a4 Kh8 35. b5 Nd8 36. Nc7 Nf7 37. N3d5 Nxd5 38. Nxd5 Kg8 39. a5 Nd6 40. b6 Kh8 41. a6 Kg8 42. a7 Kf7 43. a8=Q

badkins
2021-1-17 17:14:25

I was playing white.


badkins
2021-1-17 17:42:11

I’m pretty sure @notjack was saying that it would be “pointer sized”, not “a pointer”. In other words, a vector of bytes would take more space due to storing 64-bit values instead of 8-bit values, but the values would be immediate.


yilin.wei10
2021-1-17 17:53:00

@soegaard2, @artemchernyak The issue in the end was the grammar currently encoded is too restrictive; I’ve opened a PR for a fix but it really is a pain because SQL dialects are not all consistent.


laurent.orseau
2021-1-17 17:53:25

I believe it’s still a vector of pointers:


laurent.orseau
2021-1-17 17:53:36

#lang racket (require racket/unsafe/ops) (define v (make-vector 10 0)) (unsafe-vector-set! v 0 '(a b c)) v ; -&gt; #((a b c) 0 0 0 0 0 0 0 0 0)


yilin.wei10
2021-1-17 17:53:46

I known it works for postgresql and sqlite3 - but I don’t have too much experience with SQL server and the other ones.


laurent.orseau
2021-1-17 17:57:30

or maybe you were talking about fxvector?


soegaard2
2021-1-17 19:22:54

@pihentagy FWIW here is a helper to make a sequence (instead of a stream): #lang racket (define (make-generated-sequence initial-state next-state state-value) (let () ; The position "pos" represents the current state. ; In this example, the position is a simple integer. (define (pos-&gt;element i) (state-value i)) (define early-next-pos #f) (define (next-pos i) (next-state i)) (define initial-pos initial-state) (define (continue-with-pos? i) #t) (define continue-with-val? #f) ; only use continue-with-pos? (define continue-with-pos+val? #f) ; only use continue-with-pos? (make-do-sequence (λ () (values pos-&gt;element early-next-pos next-pos initial-pos continue-with-pos? continue-with-val? continue-with-pos+val?))))) (define squares (make-generated-sequence 0 add1 sqr)) (for/list ([x 5] [y squares]) y) The output is: '(0 1 4 9 16)


pihentagy
2021-1-17 19:30:45

Uh, that’s too complicated for me as of now. Could someone show me an implementation of in-naturals ?


soegaard2
2021-1-17 19:31:22

That would be: (make-generated-sequence 0 add1 (lambda (x) x))


soegaard2
2021-1-17 19:33:22

The initial state 0 and the next state function add1 generates a series of states: 0 1 2 3 4 5 6 ...


soegaard2
2021-1-17 19:34:03

The job of state-value is to turn the state into an element.


soegaard2
2021-1-17 19:34:18

In the sqares example sqr simply squares the state.


soegaard2
2021-1-17 19:35:06

In the in-naturals example, the state and the element is the same, so the identity function (lambda (x) x) can be used to turn the state into an element.


pihentagy
2021-1-17 19:37:45

and what about the stream-cons function. Is it not suitable to construct sequences?


soegaard2
2021-1-17 19:38:57

That’ll work too. The nomenclature with respect to sequences and streams are slightly confusing in Racket.


soegaard2
2021-1-17 19:39:16

All streams are sequences, but not all sequences are streams.


pihentagy
2021-1-17 19:39:48

eh, I meant to construct streams of course, sorry


pihentagy
2021-1-17 19:40:25

so is it possible to write in-natural with help of stream-cons? (and maybe without custom helper functions?)


soegaard2
2021-1-17 19:42:27

You could create a stream with the same elements as in-naturals have, but implementing in-naturals as a sequence, makes it possible for for to generate more efficient loops (compared to an equivalent stream).


badkins
2021-1-17 19:56:45

@laurent.orseau Doesn’t Racket have some bits to indicate fixnum? In other words, if you store a list in a vector, as you did, it would be a pointer to the list, but if you stored a fixnum, it would just be a fixnum ?


pihentagy
2021-1-17 19:59:29

And what about generators? Is it easier with them? I mean, is it simpler to create an in-naturals generator?


soegaard2
2021-1-17 20:01:24

Totally forgot that that generators exist. They can be used too. Let me look up how they work.


laurent.orseau
2021-1-17 20:02:44

ah, maybe. Though I wouldn’t count on it. Compilers aren’t always as smart as you’d like, so if you want a vector of fixnums, then you should use fxvector I guess


soegaard2
2021-1-17 20:08:03

I thought, this would work: #lang racket (require racket/generator) (define g (generator () (let loop ([state 0]) (yield state) (loop (+ state 1))))) (list (g) (g) (g)) (for/list ([x 5] [y (in-generator g)]) y) But for some reason the last line produces the empty list.


notjack
2021-1-17 20:38:02

Racket fixnums are pointer sized, but use tag bits in the pointer so that they’re stored directly within the pointer itself instead of the memory the pointer would point to


greg
2021-1-17 21:15:33

I find in-producer to be pretty handy. It works with any function that produces values. The function can return a special value to mean “stop”. But it doesn’t have to, in which case the sequence is infinite.


greg
2021-1-17 21:16:10

A few times I’ve started to look at make-do-sequence, then remember in-producer exists, and am relieved. :slightly_smiling_face:


greg
2021-1-17 21:16:39

At least, it’s been OK for my purposes. make-do-sequence probably handles more situations and/or is more performant, idk.



anything
2021-1-18 00:57:20

Cool game. You were a bit too violent for a young engine! :smile: Very nice work. To be honest, if I were writing this, I’d be happy with just being able to implement the algorithms for checking valid moves and reading and writing the PGN notation (however it’s called). You may not be too impressed yourself yet, but I certainly am! :chess_pawn:


sorawee
2021-1-18 01:46:51

@soegaard2 the name of in-generator is kinda misleading. Its body shouldn’t produce a generator, but should be the generator body itself. in-producer is the right way to do it (according to the docs)


badkins
2021-1-18 03:13:16

The algorithms, move generation, moving, searching, etc. are fun, but parsing PGN notation is just work :) Here’s a sample of tests showing various possible moves: ;; pat-pawn (for ([ pair (in-list '(("d4" (#f "d" "4" #f #f)) ("d4+" (#f "d" "4" #f "+")) ("d4#" (#f "d" "4" #f "#")) ("d8=N" (#f "d" "8" "=N" #f)) ("d8=Q+" (#f "d" "8" "=Q" "+")) ("d8=Q#" (#f "d" "8" "=Q" "#")) ("cxd4" ("cx" "d" "4" #f #f)) ("cxd4+" ("cx" "d" "4" #f "+")) ("cxd4#" ("cx" "d" "4" #f "#")) ("cxd8=B" ("cx" "d" "8" "=B" #f)) ("cxd8=R+" ("cx" "d" "8" "=R" "+")) ("cxd8=R#" ("cx" "d" "8" "=R" "#")))) ]) (match-let ([ (list str groups) pair ]) (check-equal? (regexp-match pat-pawn str) (cons str groups)))) ;; pat-piece (for ([ pair (in-list '(("Qd4" ("Q" #f #f "d4" #f)) ("Qd4+" ("Q" #f #f "d4" "+")) ("Qd4#" ("Q" #f #f "d4" "#")) ("Q3d4" ("Q" #f "3" "d4" #f)) ("Q3d4+" ("Q" #f "3" "d4" "+")) ("Q3d4#" ("Q" #f "3" "d4" "#")) ("Qcd4" ("Q" "c" #f "d4" #f)) ("Qcd4+" ("Q" "c" #f "d4" "+")) ("Qcd4#" ("Q" "c" #f "d4" "#")) ("Qc3d4" ("Q" "c" "3" "d4" #f)) ("Qc3d4+" ("Q" "c" "3" "d4" "+")) ("Qc3d4#" ("Q" "c" "3" "d4" "#")))) ]) (match-let ([ (list str groups) pair ]) (check-equal? (regexp-match pat-piece str) (cons str groups)))) ;; pat-castle (for ([ pair (in-list '( ("O-O" ("O-O" #f)) ("O-O-O" ("O-O-O" #f)) ("O-O+" ("O-O" "+")) ("O-O-O+" ("O-O-O" "+")) ("O-O#" ("O-O" "#")) ("O-O-O#" ("O-O-O" "#")) )) ]) (match-let ([ (list str groups) pair ]) (check-equal? (regexp-match pat-castle str) (cons str groups))))


badkins
2021-1-18 03:13:56

Yes, you can checkmate your opponent with a castle move :)


tom640
2021-1-18 03:25:47

@tom640 has joined the channel