; -*- scheme -*- (define (create kind energy) (list energy kind)) (define kind cadr) (define energy car) (define set-energy! set-car!) (define (check! o) (if (< (energy o) 0) (error (kind o) "is invalid"))) (define (is-meat f) (member f (list 'Beef 'Dead-rabbit 'Dead-human))) (define (invalidate! o) (set-energy! o -1)) (define invalidate-animal! invalidate!) (define (invalidate-food! o) (if (is-meat (kind o)) (set-energy! o -1))) (define (can-eat a f) (or (and (equal? a 'Cow) (equal? f 'Grass)) (and (equal? a 'Rabbit) (equal? f 'Carrot)) (and (equal? a 'Human) (or (equal? f 'Carrot) (is-meat f))))) (define (eat animal food) (check! animal) (check! food) (if (can-eat (kind animal) (kind food)) (begin (set-energy! animal (+ (energy animal) (energy food))) (invalidate-food! food)) (error (kind animal) "can't eat" (kind food)))) (define (slaughter animal) (check! animal) (let* ((a (kind animal)) (e (energy animal)) (new-kind (cond ((equal? a 'Cow) 'Beef) ((equal? a 'Rabbit) 'Dead-rabbit) ((equal? a 'Human) 'Dead-human) (else (error "can't slaughter" (kind animal)))))) (invalidate-animal! animal) (create new-kind e))) (define grass (create 'Grass 5)) (define carrot (create 'Carrot 10)) (define a_rabbit (create 'Rabbit 100)) (define a_cow (create 'Cow 1000)) (define a_human (create 'Human 300)) (define another_human (create 'Human 350)) (for-each (lambda (o) (display (kind o)) (display " -> ") (display (energy o))) (list a_rabbit a_cow a_human)) (eat a_rabbit carrot) (eat a_cow grass) (define a_dead_rabbit (slaughter a_rabbit)) (define a_beef (slaughter a_cow)) (eat a_human carrot) (eat a_human carrot) (eat a_human a_beef) (eat a_human a_dead_rabbit) (eat a_human (slaughter another_human)) (if (= (energy a_human) 1785) '() (error "failed")) ;(eat (slaughter (create 'Cow 10)) grass) ; meat (food) can't eat ;(slaughter (slaughter (create 'Cow 10))) ; meat (food) can't be slaughtered ;(eat carrot grass) ; vegetable (food) can't eat ;(slaughter carrot) ; vegetable (food) can't be slaughtered ;(eat (create 'Cow 10) carrot) ; cow do not eat carrot ;(eat (create 'Cow 10) (slaughter (create 'Cow 10))) ; cow do not eat beef ;(eat a_human (create 'Cow 10)) ; can't eat live animals ;(eat a_human grass) ; human do not eat grass ;(eat a_human a_beef) ; a_beef is already eaten ;(eat a_cow grass) ; a_cow is dead, it can't eat ;(slaughter a_cow) ; a_cow is dead, it can't be slaughtered again