Added virtually the whole of the Scittle distribution, as it proves to be

virtually necessary to do development.
This commit is contained in:
Simon Brooke 2025-09-01 12:49:14 +01:00
parent fcb023ecc5
commit 0a200aca94
741 changed files with 174111 additions and 11 deletions

View file

@ -0,0 +1,33 @@
;; COPIED FROM https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/src/tic_tac_toe/core.cljs
(ns replicant-tictactoe.core
(:require [replicant.dom :as r]
[replicant-tictactoe.game :as game]
[replicant-tictactoe.ui :as ui]))
(defn start-new-game [store]
(reset! store (game/create-game {:size 3})))
(defn main []
;; Set up the atom
(let [store (atom nil)
el (js/document.getElementById "app")]
;; Globally handle DOM events
(r/set-dispatch!
(fn [_ [action & args]]
(case action
:tic (apply swap! store game/tic args)
:reset (start-new-game store))))
;; Render on every change
(add-watch store ::render
(fn [_ _ _ game]
(->> (ui/game->ui-data game)
ui/render-game
(r/render el))))
;; Trigger the first render by initializing the game.
(start-new-game store)))
(main)

View file

@ -0,0 +1,41 @@
;; COPIED FROM https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/src/tic_tac_toe/game.cljs
(ns replicant-tictactoe.game)
(defn create-game [{:keys [size]}]
{:next-player :x
:size size})
(def next-player {:x :o, :o :x})
(defn winner? [tics path]
(when (= 1 (count (set (map tics path))))
path))
(defn get-winning-path [{:keys [size tics]} y x]
(or (winner? tics (mapv #(vector y %) (range 0 size)))
(winner? tics (mapv #(vector % x) (range 0 size)))
(when (= y x)
(winner? tics (mapv #(vector % %) (range 0 size))))))
(defn maybe-conclude [game y x]
(if-let [path (get-winning-path game y x)]
(-> (dissoc game :next-player)
(assoc :over? true
:victory {:player (get-in game [:tics [y x]])
:path path}))
(let [tie? (= (count (:tics game)) (* (:size game) (:size game)))]
(cond-> game
tie? (dissoc :next-player)
tie? (assoc :over? true)))))
(defn tic [game y x]
(let [player (:next-player game)]
(if (or (get-in game [:tics [y x]])
(<= (:size game) x)
(<= (:size game) y))
game
(-> game
(assoc-in [:tics [y x]] player)
(assoc :next-player (next-player player))
(maybe-conclude y x)))))

View file

@ -0,0 +1,50 @@
/* COPIED from https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/resources/public/styles.css */
.cell {
aspect-ratio: 1 / 1;
background: rgba(255, 255, 255, 0.8);
border-radius: 6%;
border: none;
display: block;
flex: 1 1 0%;
outline: none;
position: relative;
width: 100%;
}
.cell-content {
opacity: 1;
transition: opacity 0.25s;
}
.transparent {
opacity: 0;
}
.cell-dim {
background: rgba(249, 249, 240, 0.3);
}
.cell-highlight {
background: #fcfcf3;
}
.clickable {
cursor: pointer;
}
.board {
--gap: 0.75rem;
background: #833ab4;
background: linear-gradient(90deg, #833ab4 0%, #fd1d1d 50%, #fcb045 100%);
display: flex;
flex-direction: column;
gap: var(--gap);
padding: var(--gap);
max-width: 80vh;
}
.row {
display: flex;
flex-direction: row;
gap: var(--gap);
}

View file

@ -0,0 +1,75 @@
;; COPIED FROM https://github.com/cjohansen/replicant-tic-tac-toe/blob/7a33fb12f0cd6658b2f555ff673dee031d4aa921/src/tic_tac_toe/ui.cljs
(ns replicant-tictactoe.ui)
(def mark-x
[:svg {:xmlns "http://www.w3.org/2000/svg"
:viewBox "0 -10 108 100"}
[:path
{:fill "currentColor"
:d "m1.753 69.19.36-1.08q.35-1.09 1.92-2.97 1.58-1.87 3.85-3.84 2.29-1.97 4.6-3.54 2.31-1.57 4.93-3.24 2.62-1.66 4.65-2.9 2.04-1.23 3.91-2.27 1.87-1.05 3.98-2.31 2.11-1.27 4.12-2.5 2.01-1.24 4.33-2.51l4.6-2.52q2.27-1.25 4.84-2.86 2.56-1.62 5.03-3.09 2.47-1.47 4.5-2.88 2.03-1.4 3.82-2.82t3.81-3.47q2.01-2.06 3.7-3.51 1.69-1.46 3.47-3.03 1.77-1.57 4.01-3.69 2.24-2.11 4.13-3.7 1.89-1.58 3.93-2.97 2.04-1.39 4.05-2.49 2.01-1.11 5.26-2.54 3.24-1.44 4.48-1.46 1.24-.01 2.42.37 1.18.37 2.18 1.11 1 .74 1.71 1.75.71 1.02 1.06 2.21.34 1.19.3 2.43-.05 1.24-.5 2.39-.44 1.16-1.23 2.12-.79.95-1.84 1.61-1.05.65-2.26.94-1.21.28-2.44.16-1.23-.11-2.37-.62-1.13-.5-2.04-1.34-.91-.84-1.51-1.93-.6-1.08-.81-2.3-.22-1.22-.04-2.45.18-1.23.75-2.33.56-1.1 1.45-1.97.89-.86 2.01-1.4 1.11-.54 2.35-.69 1.23-.15 2.44.1t2.29.87q1.07.63 1.88 1.56.82.93 1.29 2.08.48 1.14.56 2.38.09 1.24-.23 2.44-.31 1.19-.99 2.23-.68 1.04-1.66 1.8-.98.76-2.15 1.18l-1.16.41-2.28 1.17q-2.28 1.18-4.38 2.7-2.1 1.51-4.2 3.44-2.1 1.92-4.18 3.7-2.08 1.77-3.9 3.44-1.81 1.68-3.41 3.13-1.6 1.46-3.38 3.09-1.79 1.62-3.44 2.97-1.66 1.34-3.53 2.4-1.88 1.06-4.17 2.65-2.3 1.6-4.79 2.74-2.48 1.14-4.98 2.71-2.5 1.57-4.51 2.47-2.01.9-3.99 1.87-1.98.97-3.88 2.02-1.91 1.05-4.38 2.34-2.46 1.28-4.94 2.53-2.47 1.25-4.48 2.38-2 1.12-3.96 2.14-1.95 1.01-3.83 1.99-1.89.98-4.37 2.05-2.48 1.06-2.96 2.01-.48.96-.78 1.49-.3.53-.71.97-.41.44-.92.77-.51.34-1.09.54-.57.2-1.17.25-.6.06-1.2-.03t-1.16-.32q-.56-.23-1.05-.59-.49-.35-.89-.82-.39-.46-.65-1.01-.27-.54-.4-1.14-.13-.59-.12-1.19.02-.6.18-1.19l.16-.59Z"}]
[:path
{:fill "currentColor"
:d "m28.099 4.991 2.69 1.97q2.69 1.96 4.5 3.22 1.8 1.28 4.54 3.46 2.74 2.18 4.57 3.89t3.38 3.72q1.54 2.02 2.88 4.3 1.34 2.28 2.83 4.46 1.48 2.18 2.63 4.14 1.15 1.96 2.74 4.07 1.59 2.1 3.59 4.19 1.99 2.08 4.23 4.48 2.24 2.4 3.7 4.04 1.47 1.64 2.91 3.23 1.44 1.59 3.08 3.58 1.64 1.99 3.51 4.08 1.87 2.09 3.55 3.77 1.69 1.68 4.1 3.51 2.42 1.83 3.9 2.58 1.48.74 2.14 1.34.66.6 1.15 1.33.5.74.8 1.57.31.84.4 1.72.1.88-.02 1.76-.12.88-.44 1.71-.33.82-.84 1.55-.51.72-1.19 1.3-.67.58-1.46.98-.79.41-1.65.61-.87.2-1.76.19-.88-.01-1.74-.24-.86-.22-1.64-.64-.78-.42-2.27-2.72-1.48-2.3-1.52-3.49-.03-1.19.31-2.33.35-1.14 1.04-2.11.69-.97 1.66-1.67.96-.7 2.1-1.05 1.14-.35 2.33-.32 1.19.02 2.31.43t2.05 1.15q.93.75 1.58 1.75.64 1 .93 2.15.29 1.16.2 2.35-.09 1.18-.56 2.28-.47 1.1-1.26 1.99-.79.88-1.83 1.47t-2.2.82q-1.17.23-2.35.07-1.19-.16-2.25-.68-1.07-.53-1.92-1.37-.84-.84-1.37-1.9-.54-1.07-.7-2.25-.17-1.18.06-2.35.22-1.17.8-2.21.58-1.04 1.47-1.84.88-.79 1.98-1.27 1.09-.47 2.28-.57 1.18-.1 2.34.18 1.16.29 2.16.93 1.01.63 1.76 1.56.74.93-.33-.26-1.07-1.18-.41-.58.66.59 1.15 1.33.5.74.8 1.57.31.83.4 1.72.1.88-.02 1.76-.12.88-.44 1.7-.33.83-.84 1.55-.51.73-1.19 1.31-.67.58-1.46.98-.79.41-1.65.61-.87.2-1.75.19-.89-.01-1.75-.24-.86-.22-1.64-.64-.78-.42-2.73-1.57-1.95-1.14-4.26-2.95-2.31-1.8-3.87-3.43-1.57-1.62-3.17-3.29-1.6-1.66-3.55-4.05-1.95-2.39-3.33-4.15-1.39-1.76-2.77-3.4-1.38-1.64-3.07-3.56-1.7-1.91-3.91-4.13-2.2-2.22-3.74-4.1-1.54-1.88-2.79-3.75-1.24-1.87-2.4-4.33t-2.39-4.46q-1.23-2.01-2.4-4.59-1.17-2.59-2.53-5.01-1.36-2.43-3.35-4.44-1.99-2.02-4.52-4.27-2.54-2.25-5.33-4.04-2.81-1.79-3.28-2.21-.47-.41-.83-.92-.35-.51-.58-1.1-.22-.58-.3-1.2-.08-.62-.01-1.23.08-.62.29-1.21.22-.58.58-1.1.35-.51.81-.93.47-.42 1.02-.71t1.16-.45q.61-.15 1.23-.15t1.22.14q.61.15 1.17.44l.55.28Z"}]])
(def mark-o
[:svg {:xmlns "http://www.w3.org/2000/svg"
:viewBox "0 0 114 114"}
[:path
{:fill "none"
:stroke "currentColor"
:stroke-linecap "round"
:stroke-width "6"
:d "M74.616 8.935c7.73 2.38 15.96 9.34 21.58 16.04 5.63 6.69 10.57 15.46 12.18 24.11 1.6 8.65.74 19.67-2.53 27.77-3.27 8.11-10.12 15.37-17.09 20.88-6.98 5.51-16.07 10.81-24.76 12.17-8.7 1.35-19.32-.76-27.42-4.06-8.1-3.29-15.73-8.93-21.21-15.73-5.48-6.81-10.32-16.5-11.67-25.09-1.35-8.6.19-18.39 3.57-26.51 3.38-8.11 9.99-16.6 16.71-22.19 6.72-5.59 13.95-10.52 23.63-11.36 9.68-.84 28.04 4.34 34.45 6.32 6.42 1.97 4.37 4.6 4.04 5.55m-48.33-9.69c7.65-3.32 19.78-3.63 28.63-2.01 8.86 1.63 17.85 5.89 24.49 11.76 6.64 5.87 12.7 15.08 15.37 23.48 2.67 8.41 2.5 18.4.65 26.95-1.85 8.54-5.98 17.59-11.77 24.34-5.78 6.74-14.56 13.05-22.93 16.11-8.37 3.06-18.75 4.19-27.29 2.25-8.54-1.93-17.37-7.89-23.96-13.87-6.59-5.97-12.89-13.58-15.57-21.96-2.69-8.39-2.31-19.94-.56-28.34 1.75-8.4 5.21-15.74 11.06-22.09 5.85-6.35 19.92-13.32 24.04-16.01 4.12-2.7.37-1.1.67-.16"}]])
(defn render-cell [{:keys [content on-click dim? highlight? clickable?]}]
[:button.cell
{:on {:click on-click}
:class (cond-> []
dim? (conj "cell-dim")
highlight? (conj "cell-highlight")
clickable? (conj "clickable"))}
(when content
[:div.cell-content
{:replicant/mounting {:class "transparent"}
:replicant/unmounting {:class "transparent"}}
content])])
(defn render-board [{:keys [rows]}]
[:div.board
(for [row rows]
[:div.row
(for [cell row]
(render-cell cell))])])
(defn render-game [{:keys [board button]}]
[:div
(render-board board)
(when button
[:button {:on {:click (:on-click button)}
:style {:margin-top 20
:font-size 20}}
(:text button)])])
(def player->mark
{:x mark-x
:o mark-o})
(defn game->ui-data [{:keys [size tics victory over?]}]
(let [highlight? (set (:path victory))]
{:button (when over?
{:text "Start over"
:on-click [:reset]})
:board
{:rows
(for [y (range size)]
(for [x (range size)]
(if-let [player (get tics [y x])]
(let [victorious? (highlight? [y x])]
(cond-> {:content (player->mark player)}
victorious? (assoc :highlight? true)
(and over? (not victorious?)) (assoc :dim? true)))
(if over?
{:dim? true}
{:clickable? true
:on-click [:tic y x]}))))}}))