src/caves/core.clj @ 06c10cd4dd4f

basic skeleton
author Steve Losh <steve@stevelosh.com>
date Sun, 08 Jul 2012 07:14:54 -0400
parents 28faced3ca08
children 17efffc997c6
(ns caves.core
  (:require [lanterna.screen :as s]))


; Data Structures -------------------------------------------------------------
(defrecord UI [kind])
(defrecord World [])
(defrecord Game [world uis input])

; Utility Functions -----------------------------------------------------------
(defn clear-screen [screen]
  (let [blank (apply str (repeat 80 \space))]
    (doseq [row (range 24)]
      (s/put-string screen 0 row blank))))


; Input -----------------------------------------------------------------------
(defmulti process-input
  (fn [ui input game]
    (:kind ui)))

(defmethod process-input :start [ui input game]
  (if (= input :enter)
    (assoc game :uis [(new UI :win)])
    (assoc game :uis [(new UI :lose)])))

(defmethod process-input :win [ui input game]
  (if (= input :escape)
    (assoc game :uis [])
    (assoc game :uis [(new UI :start)])))

(defmethod process-input :lose [ui input game]
  (if (= input :escape)
    (assoc game :uis [])
    (assoc game :uis [(new UI :start)])))

(defn get-input [game screen]
  (assoc game :input (s/get-key-blocking screen)))


; Drawing ---------------------------------------------------------------------
(defmulti draw-ui
  (fn [ui game screen]
    (:kind ui)))

(defmethod draw-ui :start [ui game screen]
  (s/put-string screen 0 0 "Welcome to the Caves of Clojure!")
  (s/put-string screen 0 1 "Press enter to win, anything else to lose."))

(defmethod draw-ui :win [ui game screen]
  (s/put-string screen 0 0 "Congratulations, you win!")
  (s/put-string screen 0 1 "Press escape to exit, anything else to restart."))

(defmethod draw-ui :lose [ui game screen]
  (s/put-string screen 0 0 "Sorry, better luck next time.")
  (s/put-string screen 0 1 "Press escape to exit, anything else to go."))

(defn draw-game [game screen]
  (clear-screen screen)
  (doseq [ui (:uis game)]
    (draw-ui ui game screen))
  (s/redraw screen))


; Main ------------------------------------------------------------------------
(defn run-game [game screen]
  (loop [{:keys [input uis] :as game} game]
    (when-not (empty? uis)
      (draw-game game screen)
      (if (nil? input)
        (recur (get-input game screen))
        (recur (process-input (last uis) input (dissoc game :input)))))))

(defn new-game []
  (new Game
       (new World)
       [(new UI :start)]
       nil))

(defn main [screen-type]
  (future
    (let [screen (s/get-screen screen-type)]
      (s/in-screen screen
                   (run-game (new-game) screen)))))


(defn -main [& args]
  (let [args (set args)
        screen-type (cond
                      (args ":swing") :swing
                      (args ":text")  :text
                      :else           :auto)]
    (main screen-type)))


(comment
  (main :swing))