Created
April 21, 2014 20:16
-
-
Save Nectarineimp/11155095 to your computer and use it in GitHub Desktop.
2048 Machine Learning Mucking About
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;; 2048 machine learning analysis | |
| ;; Order, Free Space, Weight Distribution | |
| ;; Scoring Analysis, Nabla ∇ Divergence | |
| ;; initial board state - choose wisest direction for move (up down left right) | |
| ;; 2 0 2 4 0 pairs (actually a scoring pair is in there once the space is crossed.) | |
| ;; 2 2 4 0 1 pair | |
| ;; 4 4 0 0 1 scoring pair, 1 blank pair | |
| ;; 4 0 8 0 1 blank pair | |
| (def board '((2 0 2 4) (2 2 4 0) (4 4 0 0) (4 0 8 0))) | |
| (def max-spaces 16) | |
| (def max-pairs 24) | |
| (def half-board (/ (count board) 2)) | |
| ;; Order Analysis | |
| ;; We want to determine how ordered the board is. A board with a lot | |
| ;; of space is considered very ordered as is one with lots of pairs | |
| ;; of numbers on it. Order is good because it means we can score. | |
| (defn get-vertical [coll] | |
| (apply map list coll)) | |
| (defn count-pairs [coll] | |
| (->> coll | |
| (partition 2 1) | |
| (filter (fn [[a b]] (= a b))) | |
| count)) | |
| (def rotated-board (get-vertical board)) | |
| (partition 2 1 board) | |
| (defn pairs [coll rotated-coll] (+ (apply + (map count-pairs coll)) | |
| (apply + (map count-pairs rotated-coll)))) | |
| (pairs board rotated-board) | |
| (def ratio-pairs (/ (pairs board rotated-board) max-pairs)) | |
| ratio-pairs | |
| ;; This is how ordered the board is. Bigger is Better! | |
| ;; Free Space Analysis | |
| ;; The less space we have the less movement we will have. We need | |
| ;; space to make good pairs. If we are running low on space we | |
| ;; want to put empahasis on moves that reduce space. | |
| (defn filter-zero [coll] | |
| (filter (fn [a] (= 0 a)) coll)) | |
| (defn count-spaces [coll] (count (flatten (map filter-zero coll)))) | |
| (defn space-ratio [coll] (/ (count-spaces coll) max-spaces)) | |
| ;; This is how much free space is in the board as a ratio. Bigger is Better! | |
| ;; Weight Distribution | |
| ;; We can tell which direction has the most high value numbers. | |
| ;; Since we know 2's and 4's come up as new tiles, we can set it | |
| ;; up so the most 2's and 4's are exposed. | |
| (def weight-vector (vector | |
| (apply + (flatten (take half-board board))) | |
| ;; Top | |
| (apply + (flatten (nthrest board half-board))) | |
| ;; Bottom | |
| (apply + (flatten (take half-board rotated-board))) | |
| ;; Left | |
| (apply + (flatten (nthrest rotated-board half-board))) | |
| ;; Right | |
| )) | |
| ;; This will help us decide which direction to choose | |
| ;; if we end up with a tie. | |
| ;; Scoring Analysis | |
| ;; Determine the current scoring potential, the density | |
| ;; of points on tiles, and total points on tiles. | |
| (defn total-points [coll] | |
| (apply + (flatten board))) | |
| (def total-points-initial (total-points board)) | |
| (def not-zero? (complement zero?)) | |
| (defn point-density [coll] | |
| (/ | |
| (total-points coll) | |
| (count (filter not-zero? (flatten board))))) | |
| (point-density board) | |
| ;; Bigger is better! | |
| (defn get-runs [coll] | |
| (map #(partition-by identity %) (map #(filter not-zero? %) coll))) | |
| (def runs-board (get-runs board)) | |
| (def runs-rotated-board (get-runs rotated-board)) | |
| (def two-plus? (fn [x] | |
| (> (count x) 1))) | |
| (defn get-scoring-runs [coll] | |
| ;; reduces the total runs into just scoring runs | |
| (map #(filter two-plus? %) (get-runs coll)) | |
| ) | |
| (defn get-scoring-run-sizes [coll] | |
| (map #(map count %) (get-scoring-runs coll)) | |
| ) | |
| (get-scoring-run-sizes board) | |
| (get-scoring-run-sizes rotated-board) | |
| (def scoring-runs-board (get-scoring-runs board)) | |
| (def scoring-runs-rotated-board (get-scoring-runs rotated-board)) | |
| (defn sub-score [coll] | |
| ;; Calculate score depending on how many numbers are in the run. | |
| ;; Count 2 and 3, double the first number. | |
| ;; Count 4, quadruple the first number. | |
| (if (> 4 (count coll)) (* 2 (first coll)) (* 4 (first coll)))) | |
| (defn score-potential [coll] | |
| (apply + (flatten (map #(map sub-score %) coll)))) | |
| ;; Board should score 4+4+8 = 16 | |
| ;; Rotated Board should score 4 | |
| scoring-runs-board | |
| scoring-runs-rotated-board | |
| (score-potential scoring-runs-board) | |
| (score-potential scoring-runs-rotated-board) | |
| ;; This tells us that a left or right shift will get us more points | |
| ;; than an up or down shift. | |
| ;; Nabla ∇ Divergence | |
| ;; This is an analysis of how many options of movement will be left | |
| ;; within the board. It produces three numbers. The first two are | |
| ;; the number of rows and columns which can still move. | |
| ;; The third is the number of new spaces created. Calculating | |
| ;; existing divergence and future divergence of choices presents | |
| ;; an interesting analysis that fits in with the mathmatical | |
| ;; statement of intelligence which says choose the path of greater | |
| ;; divergence. | |
| (defn agility [coll] | |
| ;; agility is the movement potential based on a row having | |
| ;; free space. A row has either 0 or 1 agility and | |
| ;; a board has 0 thru 4 agility. | |
| ;; If a row has nothing but spaces it has 0 agility. | |
| ;; So given a board with one clear row and 3 full rows, | |
| ;; for example, then the agility of left-right would be 0 | |
| ;; and up-down would be 4. | |
| (apply + (map #(if (and (not-empty? %) (> 4 (count %))) 1 0) (map filter-zero coll))) | |
| ) | |
| (agility board) | |
| ;; left-right agility | |
| (agility rotated-board) | |
| ;; up-down agility | |
| (defn created-space [coll] | |
| ;; This is a prediction of how much space could be created by choosing a particular direction. | |
| ;; When space is at a premium this becomes a very important strategy. Ignoring high value moves | |
| ;; for low value but space clearing moves becomes an important option. | |
| (->> coll | |
| get-scoring-run-sizes | |
| (map #(apply + %)) | |
| (map #(cond (= 2 %) 1 (= 3 %) 1 (= 4 %) 2 (= 0 %) 0)) | |
| (apply +)) | |
| ) | |
| (created-space board) | |
| ;; left-right swipe | |
| (created-space rotated-board) | |
| ;; up-down swipe | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment