procgen  Artifact [d5281d581a]

Artifact d5281d581afe5872b1a5e0ea222b8b14f36382a48d0299b88b511d40cc55e110:


; [ʞ] bot.scm
;  ~ lexi hale <lexi@hale.su>
;  © affero general public license
;  > (load "lib/lisp-macro.scm")
;    (load "lib/bot.scm")

; prep the random number generator
(import (chicken random))
(set-pseudo-random-seed! (random-bytes))

; generates a (case) structure that randomly returns
; one of its branches at equal probability
(define-for-syntax (@one-of case-fn strs)
  ; attach a unique integer value to every item in the
  ; list, descending from (length strs) to 0
  (define (zip lst)
	; inefficient but fun(ctional) way
	(define (long-cons acc new)
	  (cons (cons (length acc) new) acc))
	(foldl long-cons '() lst)) 

  ; return the following list structure
  `(case (pseudo-random-integer ,(length strs))
	 ,@(map case-fn (zip strs))))

; create the case structure for rule expansion
(define-for-syntax (@rewrite-patterns patterns)
  (define (nest-case pair)
	(cons (list (car pair))
		  (cdr pair)))

  (define (wrap pat) 
	(if (eq? (cdr pat) '()) ;then
		pat
	; else
		(list (cons 'string-append pat))))

  (let ([branches (map wrap patterns)])
	(@one-of nest-case branches)))


; exports

	; randomly select and return one of its arguments at runtime
	(define-macro (one-of . strs)
				  (define (flat-case pair)
					(list (list (car pair))
						  (cdr pair)))
				  (@one-of flat-case strs))

	; generates a function that picks and applies one of the
	; patterns passed to it. inner patterns can be expanded
	; with the inner macro (@)
	(define-macro (rule . body)
				  (let ([decl (car body)]
						[patterns (cdr body)])
					`(define ,decl
					   (define-macro (@ . tree) (@rewrite-patterns tree)) ;choice point
					   (define-macro (: . tree) (@rewrite-patterns (cons (list "") tree))) ;optional choice
					   (define-macro (? . tree) (@rewrite-patterns (cons (list "") (list tree)))) ;optional - TODO: rewrite
					   ,(@rewrite-patterns patterns))))
	; generate simple word-banks
	(define-macro (bank . body)
				  (let ([decl (car body)]
						[patterns (cdr body)])
					`(define (,decl)
							 (one-of ,@patterns))))
	(define (pick ar)
		(vector-ref ar (pseudo-random-integer (vector-length ar))))