#lang r7rs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Timer ADT ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Manages the countdown time limit. Contains NO graphics code. (define-library (pacman-project adt-timer) (import (scheme base) (pacman-project constants)) (export make-timer) (begin ;; make-timer :: -> timer ;; Creates a new timer object. (define (make-timer) (let ((remaining-time start-time-seconds) (time-since-last-tick 0)) ;; decrease! :: number -> / ;; Decreases time based on elapsed milliseconds. (define (decrease! ms) (set! time-since-last-tick (+ time-since-last-tick ms)) (when (>= time-since-last-tick ms-per-second) (set! time-since-last-tick 0) (when (> remaining-time 0) (set! remaining-time (- remaining-time 1))))) ;; increase! :: -> / ;; Adds a time bonus (when eating a coin). (define (increase!) (set! remaining-time (+ remaining-time time-bonus-per-coin))) ;; time-up? :: -> boolean (define (time-up?) (= remaining-time 0)) ;; format-time :: -> string ;; Returns remaining time as "m:ss" string. (define (format-time) (let* ((minutes (quotient remaining-time 60)) (seconds (remainder remaining-time 60)) (min-str (number->string minutes)) (sec-str (number->string seconds))) (string-append min-str ":" (if (< seconds 10) (string-append "0" sec-str) sec-str)))) ;; dispatch-timer :: symbol -> any (define (dispatch-timer msg) (cond ((eq? msg 'remaining-time) remaining-time) ((eq? msg 'decrease!) decrease!) ((eq? msg 'increase!) increase!) ((eq? msg 'time-up?) time-up?) ((eq? msg 'format-time) format-time) (else (error "Timer ADT -- Unknown message:" msg)))) dispatch-timer))))