Skip to content

Instantly share code, notes, and snippets.

@tormaroe
Created March 23, 2014 01:00
Show Gist options
  • Save tormaroe/9716815 to your computer and use it in GitHub Desktop.
Save tormaroe/9716815 to your computer and use it in GitHub Desktop.
My implementation in Scheme of the game Word, that was published in BASIC Computer Games in 1978.
(use srfi-13 extras)
(define header #<<EOF
--------------------------------------------------------------------
WORD
Adaption of original game in BASIC by Charles Reid of Lexington High
School, Massachusetts. Scheme version by Torbjørn Marø, 2014.
--------------------------------------------------------------------
I am thinking of a word -- you guess it. I will give you clues to
help you get it. Good luck!!
EOF
)
(define words
'("SMOKE" "CANDY" "DINKY" "WATER" "TRAIN" "NIGHT" "MIGHT" "FIRST"
"CHAMP" "WOULD" "CLUMP" "DOPEY" "CRUSH" "EXTRA" "BASIC" "EIGHT"))
(define (random-elem lst)
(list-ref lst (random (length lst))))
(define (random-sort l)
(sort l
(lambda (x y)
(equal? 0 (random 2)))))
;;; The GAME-STATE data type
(define-record game-state word
current-guess
continue
matches
exact-matches
guess-count)
(define (init-game)
(make-game-state
(random-elem words) ; word
" " ; current-guess
#t ; continue
'() ; matches
"-----" ; exact-matches
0)) ; guess-count
(define (game-state-correct? state)
(equal? (game-state-exact-matches state)
(game-state-word state)))
;;; REPL logic
(define (game-read state)
(display "\nGuess a five letter word? ")
(let ((input (read-line)))
(cond ((equal? input "?")
(game-state-current-guess-set! state "?")
state)
((= 5 (string-length input))
(game-state-current-guess-set! state
(string-upcase input))
(game-state-guess-count-set! state
(+ (game-state-guess-count state) 1))
state)
(else
(display "Bad input length! ")
(game-read state)))))
(define (find-matches state)
(let loop ((i 0) (matches '()) (exact "-----"))
(cond
((< i 5)
(let ((c (substring (game-state-word state) i (+ i 1)))
(guess (game-state-current-guess state)))
(when (string-contains guess c)
(set! matches (cons c matches))
(when (= i (string-index guess (string->char-set c)))
(set! exact (string-replace exact c i (+ i 1))))))
(loop (+ i 1) matches exact))
(else
(game-state-matches-set! state (random-sort matches))
(game-state-exact-matches-set! state exact)))))
(define (game-eval state)
(let ((guess (game-state-current-guess state)))
(if (equal? guess "?")
(game-state-continue-set! state #f)
(find-matches state)))
state)
(define (game-print state)
(when (game-state-continue state)
(printf
"There were ~A matches and the common letters were.. ~A~%"
(length (game-state-matches state))
(apply string-append (game-state-matches state)))
(printf
"From the exact letter matches, you know........... ~A~%"
(game-state-exact-matches state))
(if (game-state-correct? state)
(printf
"You have guessed the word. It took ~A guesses!~%"
(game-state-guess-count state))
(printf
"~%If you give up, type '?' for your next guess.~%")))
state)
(define (start-game)
(display "\nYou are starting a new game...\n")
(let loop ((state (init-game)))
(when (and (game-state-continue state)
(not (game-state-correct? state)))
(loop (game-print
(game-eval
(game-read state)))))))
;;; MAIN
(define (yes-or-no)
(equal? "Y" (string-upcase (substring (read-line) 0 1))))
(display header)
(let loop ()
(start-game)
(display "Want to play again? ")
(if (yes-or-no)
(loop)
(display "\nThanks for playing - bye bye!\n\n")))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment