<commit_before>(ns blue-salamander.blockmaze
  (:require [thi.ng.geom.core.vector :as v :refer [vec2 vec3]]))


;;
;; generate a standard maze made up of n * n blocks
;;

;;
;; tiles are maps that contain keys for each direction (n,e,s,w) and
;; values that are true if you can travel in the direction specified
;; in the key. for example:
;;
;; {:n true :e true :s false :w false :used true}
;;
;; is a tile with openings to the north and the east.
;;
;; The 'used' key is true if the tile is attached to the maze. All tiles
;; start out unused except for the start tile. The maze is built by
;; iteratively connecting used tiles to adjacent unused tiles.
;;

(defn find-used-tile [mazetiles]
  (rand-nth (filter (fn [[[x y] data]] (:used data)) mazetiles)))

(defn mark-tile-used [mazetiles tile-coord]
  {:pre [(vector? tile-coord)
         (not (nil? (get mazetiles tile-coord nil)))]}
  (update-in mazetiles [tile-coord] #(assoc % :used true)))

(defn pick-adjacent-tile [[tx ty] maze-size]
  (let [candidate-tiles [[:w [(- tx 1) ty]]
                         [:e [(+ tx 1) ty]]
                         [:n [tx (- ty 1)]]
                         [:s [tx (+ ty 1)]]]
        is-legal-tile (fn [[direction-keyword [x y]]]
                        (and (>= x 0)
                             (>= y 0)
                             (< x maze-size)
                             (< y maze-size)))
        legal-tiles (filter is-legal-tile candidate-tiles)]
    (rand-nth legal-tiles)))

(defn opposite-dir [dir]
  (get {:w :e
        :e :w
        :n :s
        :s :n} dir))

(defn gen-empty-maze [maze-size]
  (let [initial-tile-state {:used false :n false :s false :w false :e false}
        maze-range (range maze-size)]
    (into {} (for [x maze-range
                   y maze-range]
               [[x y] initial-tile-state]))))

(defn try-to-add-branch [maze-tiles maze-size]
  (let [;; pick a tile that's already part of the maze to branch from
        branch-tile (find-used-tile maze-tiles)
        [branch-coord branch-data] branch-tile
        ;; try to branch off by picking an adjacent tile random
        [adjacent-dir adjacent-coord] (pick-adjacent-tile branch-coord maze-size)
        adjacent-tile (get maze-tiles adjacent-coord)]
    ;; we need an unused adjacent tile to branch into. If the adjacent tile is
    ;; used, do nothing
    (if (:used adjacent-tile)
        maze-tiles
        (-> maze-tiles
            ;; connect the tiles together. We mark the relvant directions on each
            ;; tile true.
            (assoc-in [branch-coord adjacent-dir] true)
            (assoc-in [adjacent-coord (opposite-dir adjacent-dir)] true)
            ;; the adjacent tile is now connected to the maze, so mark it used
            (assoc-in [adjacent-coord :used] true)))))

(defn gen-maze [maze-size]
  ;; each tile is a map describing which directions are open to adjacent tiles
  ;; and a flag indicating if it has been used or not
  (let [empty-tiles (gen-empty-maze maze-size)
        start-coord [0 0]
        initial-tiles (mark-tile-used empty-tiles start-coord)
        branch-attempts (* maze-size maze-size 10)]
    ;; just keep trying to add tiles to the maze by repeatedly branching off of tiles
    ;; already in the maze.
    (nth
     (iterate #(try-to-add-branch % maze-size) initial-tiles)
     branch-attempts)))

;;
;; convert the maze data into geometry descriptions for rendering and collision<commit_msg>Needs longer maze build. Should re-write to guarantee whole maze is built!<commit_after>(ns blue-salamander.blockmaze
  (:require [thi.ng.geom.core.vector :as v :refer [vec2 vec3]]))


;;
;; generate a standard maze made up of n * n blocks
;;

;;
;; tiles are maps that contain keys for each direction (n,e,s,w) and
;; values that are true if you can travel in the direction specified
;; in the key. for example:
;;
;; {:n true :e true :s false :w false :used true}
;;
;; is a tile with openings to the north and the east.
;;
;; The 'used' key is true if the tile is attached to the maze. All tiles
;; start out unused except for the start tile. The maze is built by
;; iteratively connecting used tiles to adjacent unused tiles.
;;

(defn find-used-tile [mazetiles]
  (rand-nth (filter (fn [[[x y] data]] (:used data)) mazetiles)))

(defn mark-tile-used [mazetiles tile-coord]
  {:pre [(vector? tile-coord)
         (not (nil? (get mazetiles tile-coord nil)))]}
  (update-in mazetiles [tile-coord] #(assoc % :used true)))

(defn pick-adjacent-tile [[tx ty] maze-size]
  (let [candidate-tiles [[:w [(- tx 1) ty]]
                         [:e [(+ tx 1) ty]]
                         [:n [tx (- ty 1)]]
                         [:s [tx (+ ty 1)]]]
        is-legal-tile (fn [[direction-keyword [x y]]]
                        (and (>= x 0)
                             (>= y 0)
                             (< x maze-size)
                             (< y maze-size)))
        legal-tiles (filter is-legal-tile candidate-tiles)]
    (rand-nth legal-tiles)))

(defn opposite-dir [dir]
  (get {:w :e
        :e :w
        :n :s
        :s :n} dir))

(defn gen-empty-maze [maze-size]
  (let [initial-tile-state {:used false :n false :s false :w false :e false}
        maze-range (range maze-size)]
    (into {} (for [x maze-range
                   y maze-range]
               [[x y] initial-tile-state]))))

(defn try-to-add-branch [maze-tiles maze-size]
  (let [;; pick a tile that's already part of the maze to branch from
        branch-tile (find-used-tile maze-tiles)
        [branch-coord branch-data] branch-tile
        ;; try to branch off by picking an adjacent tile random
        [adjacent-dir adjacent-coord] (pick-adjacent-tile branch-coord maze-size)
        adjacent-tile (get maze-tiles adjacent-coord)]
    ;; we need an unused adjacent tile to branch into. If the adjacent tile is
    ;; used, do nothing
    (if (:used adjacent-tile)
        maze-tiles
        (-> maze-tiles
            ;; connect the tiles together. We mark the relvant directions on each
            ;; tile true.
            (assoc-in [branch-coord adjacent-dir] true)
            (assoc-in [adjacent-coord (opposite-dir adjacent-dir)] true)
            ;; the adjacent tile is now connected to the maze, so mark it used
            (assoc-in [adjacent-coord :used] true)))))

(defn gen-maze [maze-size]
  ;; each tile is a map describing which directions are open to adjacent tiles
  ;; and a flag indicating if it has been used or not
  (let [empty-tiles (gen-empty-maze maze-size)
        start-coord [0 0]
        initial-tiles (mark-tile-used empty-tiles start-coord)
        branch-attempts (* maze-size maze-size 20)]
    ;; just keep trying to add tiles to the maze by repeatedly branching off of tiles
    ;; already in the maze.
    (nth
     (iterate #(try-to-add-branch % maze-size) initial-tiles)
     branch-attempts)))

;;
;; convert the maze data into geometry descriptions for rendering and collision
{'fraction_non_alphanumeric': 0.12354379404573565, 'fraction_numerical': 0.003451747447145117, 'mean_word_length': 2.2770970782280866, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6065605', 'n_tokens_mistral': 2261, 'n_tokens_neox': 2130, 'n_words': 808}