diff --git a/.gitignore b/.gitignore
index 8a25d13..7a9816f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,12 @@
*.iml
.gradle
/local.properties
-/.idea
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
@@ -10,7 +15,3 @@
local.properties
node_modules
*.zip
-app/release/
-.parcel-cache/
-dist
-keystore.properties
\ No newline at end of file
diff --git a/Readme.md b/Readme.md
index e380439..681219b 100644
--- a/Readme.md
+++ b/Readme.md
@@ -2,601 +2,98 @@
Break colourful bricks, catch bouncing coins and select powerful upgrades !
-- [Play now](https://breakout.lecaro.me/)
-- [Donate](https://paypal.me/renanlecaro)
-- Bitcoin : bc1qlh8kywy3ttsuqqa08yx2rdc8dqhdvyt43wlxmr
-- [Discord](https://discord.gg/bbcQw4x5zA)
-- [itch.io](https://renanlecaro.itch.io/breakout71)
-- [F-Droid](https://f-droid.org/en/packages/me.lecaro.breakout/)
-- [Google Play](https://play.google.com/store/apps/details?id=me.lecaro.breakout)
-- [GitLab](https://gitlab.com/lecarore/breakout71)
-
-# Changelog
-## To do
+
-## Done
+[Play now](https://breakout.lecaro.me/) -
+[Google Play](https://play.google.com/store/apps/details?id=me.lecaro.breakout) -
+[itch.io](https://renanlecaro.itch.io/breakout71) -
+[GitLab](https://gitlab.com/lecarore/breakout71) -
+[Donate](https://github.com/sponsors/renanlecaro)
-- performance tweaks suggestions
+## Gameplay
-## 29106110
-- reworked level up screen :
- - bigger "level X / Y cleared"
- - upgardes need to all be spent on the same list of perks (to avoid reading too much)
- - instead of rerolls, you get a longer list of choices to pick from with silver/gold medals
- - clarified challenges, only show them when you pass one of them
- - removed the "sides bounce" challenge, bouncing on sides shouldn't be punished
- - once you reach high score of 1000, level unlock hints appear, and required / forbidden upgrades and colored gold/red
- - added tooltip on most items on that screen, that can be triggered on mobile by tapping the text
+The goal is to catch as many coins as possible during 7 levels. Coins appear when you break bricks. They fly around, bounce and roll, and you need to catch them with your puck. Your "combo" is the number of coins spawned when a brick breaks, it is displayed on your puck. Your score is displayed in the top right corner of the screen, it is the number of coins you have managed to catch since the begining of your run.
-- new perk : steering
-- boosted perk : stronger foundation (+3 combo, then +4, then +5..)
-- easy cleanup special effect (and X made of particles)
-- added a few levels
-- level end countdown (on mobile and desktop)
-- level start countdown (on mobile)
-- loosing ball is ok during level end countdown
+At the end of each level, you get to pick an upgrade from a random selection. Many upgrades impact your "combo". Upgrades apply to the whole run and can synergize. For example, "hot start" increases your combo greatly at the start of each level, but makes it tick down rapidly. If you combine it with "+1 ball", "piercing" and "bricks become bombs", you'll clear levels so fast that the combo will still be high when the fireworks are over and your puck will be showered by coins.
-- unlocked upgrades and levels : split item description (with tooltip) and "try" button
-- creative mode : removed tooltips for perks as they were getting in the way on mobile
-- Fix: removed progress bars from unlocked level as there's no real progress
-- Fix :upgrades list now uses numbers instead of bars, looks better with limitless
-- Fix :somehow score clicks didn't register while the game was playing, that's solved
-- Fix : click tooltip to open on mobile, click anywhere to close
-- Fix: Can't press help buttons in Creative Menu
-- Fix: wait for bricks to respawn before leveling up
-- UX : score and menu button look extra clickable until you tap them 3 times and restart the app
+What decides how the ball flies away is only the position of the puck hit. The puck speed and incoming angle have no impact. You must delete all bricks to progress to the next level, and never drop the ball.
-## 29097764
+After clearing a level, you'll be able to pick upgrades among a small selection presented to you. They'll apply until the end of the run. A normal run lasts 7 levels, after which your score is recorded, and you can start again. Each run is different, the levels and upgrades you see will change every time, and new ones get added to the pool when you progress in the game.
-- Added levels : Fish, Spider, GlidersLone island,Spacewyrm Jon, Taijitu, Egg pan, Inception, Chess
+The app should work offline and perform well even on low-end devices. It's very lean and does not take much storage space (Roughly 0.1MB). If the app stutters, turn on "fast mode" in the settings to render a simplified view that should be faster.
-## 29095000
+There's also an easy mode for kids (slower ball) and a color-blind mode (no color related game mechanics).
-- hardcoded the levels unlock conditions so that they wouldn't change at each update
-- added a "display level code" button in level editor
-- passive income : paddle will be transparent for a much shorter time
-- better mobile mode detection
-- clear tooltip on page scroll
+## Doing
+- publish on Fdroid
-## 29092809
-
-- fixed: crash when running out of levels (i think, i didn't try)
-- fixed: context menu and tooltip stuck on windows
-
-## 29091656
-
-- categorized the icons
-- color coded the icons
-- changed the wording of perks help to be shorter
-- added tooltips on perks with full help, and a help button on mobile
-- all or nothing : don't show negative number of coins cought, don't reduce score if no combo was lost
-- rename hypnosis to golden_goose, apply when hitting any brick, any side at level 2
-- removed comboIncreaseTexts option
-- minefield : +10% coins per bomb on screen
-- extra life are transparent when you have 2+ balls
-- removed : instant_upgrade
-- nerfed : helium : now need to be level 3 to have the same effect of keeping coins up
-- new level : Blinky by Big Goober
-- game over screen : perk list at the bottom, after unlocks and stats
-
-## 29088680
-
-- new perk: happy family: + lvl points per paddle bounce per extra ball, reset on ball lost
-- nerfed perk : sticky coins : stick to same color at level 1, any color at level 2+
-- nerfed perk: zen : combo increases every 3 seconds, resets on explosion
-
-## 29088513
-
-- included german corrections by Pock
-- added particle effect for wrap
-- removed grace period from passive income, updated icon
-
-## 29087440
-
-- zen : now you gain one combo per bomb on screen when breaking a brick (so no bombs, no gain)
-- sticky coins : coins stay stuck when there's an explosion
-- wrap_left / wrap_right : teleport the ball to the other side of the screen when it hits a border
-- passive income : now moving the puck makes it transparent to coins and balls, but not reset the combo
-- main menu : split level unlock and perks unlocks
-
-## 29087252
-- apply percentage boost to combo shown on brick
-- smaller puck now gives +50% coins per level
-- transparency now gives +50% coins if ALL balls are fully transparent, less otherwise
-- new perk : sticky coins (coins stick to bricks)
-- left/top/right is laval perks : at level 2+, the corresponding borders completely disappears (reachable with limitless)
-- new perk : three cushion (gain point for indirect hits)
-- live stats: coins still in the air appear as "lost" in the catch percentage, as in the final computation
-- level editor : removed the conditions on bricks count, level name and credits to be able to copy the code
-- shadow around ball when there are many coins : enabled in basic mode too
-- hot start : after reset, if you raise the combo again, only start ticking down after a whole second.
-- new perk : ottawa treaty, breaking a brick near a bomb disarms the bomb
-- shocks now doesn't add ball speed at level 1
-- creative mode UI rework
-- compound_interest : combo resets as soon as coin passes the paddle line
-- added bombs to implosion and kaboom starter levels
-- toast an error if storage is blocked
-- toast an error if migration fails
-- fixed video download in apk
-- ask for permanent storage
-- option: reuse past frame's light in new frame lighting computation when there are 150+ coins on screen, to limit the performance impact of rendering lots of lights
-
-## 29084606
-
-- simpler and more readable encoding for save files
-- removed check of payload signature on save file, seemed to fail because of the poor encoding of the name of the "côte d'ivoire" level
-- automatic detection of the number of steps required for physics
-- trial runs detection fix
-
-## 29083397
-
-- highlight last used creative level
-- access autoplay mode from the menu
-- access stress test mode from the menu, show real time stats
-- Render bottom border differently to show how far the puck can go
-- Corner Shot: scale like Need Some Space
-- grey out irrelevant options in the settings
-- Back to Creative Menu at the end of a Creative level
-
-## 29080170
-
-- don't show unlock toast at first startup for levels that are unlocked by default
-- Droplet particle color should be gold for gold coins
-- added levels: A Very Dangerous High-Five, The Boys
-
-## 29079818
-
-- Imported levels : Mario, Minesweeper and Target
-- Fixed an issue with localstorage saving of custom levels
-
-
-## 29079805
-
-- combo text on paddle will be grey if we're at the base combo
-- transparency now rounds up
-- import level up to 21 x 21
-- corrected icon of "padding"
-
-## 29079087
-
-- measured and improve the performance (test here https://breakout.lecaro.me/?stresstest)
-- added a few levels
-- autoplay mode (with wake lock and computer play https://breakout.lecaro.me/?autoplay )
-- Added particle and sound effect when coin drops below the "waterline" of the puck
-- slower coins fall once they are under the paddle
-- in game level editor
-- allow loading newer save in outdated app (for rollback)
-- game crashes when reaching level 12 (no level info in runLevels)
-
-## 29074385
-
-- added back some extra languages
-- superhot: fixed particles durations and level duration
-- bricks aattract coins : less powerfull
-- bricks attract balls
-- unbounded nerf : just adds padding around bricks, not combo add
-- don't tell user to get -100 points to unlock level
-- display colored coins when there's hypnosis or rainbow enabled
-
-## 29071903
-
-- new perk : hypnosis
-- new perk : rainbow
-- new perk : bricks attract coins
-- Extra choice: wrong text for french "2 more choices"
-- metamorphosis : when coins are spent, display them hollowed out
-- super hot : starting level rework
-- zen : added bombs to starting level
-
-## 29071527
-
-- super hot : time moves only when paddle moves. Later levels slow down even more the time when you're not moving.
-- transparency : ball becomes transparent towards top of screen, +50% coins.
-- space coins : coins bounce without loosing momentum
-- trickledown : coins spawn at the top of the screen
-- unlocked content : start with perk icon as level
-- allow removing all starting perks, to get full random
-- rename "puck" into paddle
-- use french as base language to keep consistent formal/informal tone
-- fixed memory leak in language detection code
-
-## 29069860
-
-- when rendering level icons, always use transparent background
-- resized some levels to use as flags, added some missing languages as levels
-- added machine translation, so that translators can try the game in their language first : ar,de,es,ko,ru,ur,uz,zh
-- change translation keys to get better sorted files
-- change fortunate ball to work more like coin magnet, carrying the balls around to catch them at next puck bounce
-- add a test to forbid more than 5% grey bricks on black background, remove grey bricks border
-- simplified texts to make translation easier
-- fixed some issues around saved level unlocks
-- change donation text to not suggest an amount
-- limited history to top 100 runs
-
-## 29068563
-
-- review the "next unlocks" in score and game over
-- As soon as upgrade condition is reached, toast
-- As soon as level condition is reached, lock it in and tell the user
-- extra life only saves your last ball, max 7 instead of 3
-- Don't use "RAZ" in French explanations.
-- explain ghost coin's slow down effect
-- when there are only a few coins, make them brighter
-- Perk : [colin] minefield
-- clear scheduled sounds if sounds off
-- show unlocked levels above game stats in gameover screen
-- reduce resolution of lights even more (1/16)
-
-## 29067205
-
-- tooltip isn't readable at bottom of screen
-- added levels as tributes to game players
-- display closest unlock with current perks in score and gameover screens
-- initial perk icon = first level
-- fix starting perk option not working
-- progress bar for unlock in unlocks menu
-- display runs history
-- in the runs history, only save perks that were chosen by the user
-- migration to save past content to localStorage.recovery_data right before starting a new version
-- mention unlock conditions in help
-- show unlock condition in unlocks menu for perks as tooltip
-- fallback for mobile user to see unlock conditions
-- New perk : "limitless" raises the max of all perks by 1
-- Boosted perk : side kick, now you just need to hit bricks from the left side to gain +lvl combo, hitting from the right side does -2xlvl combo
-- add unlock conditions for levels in the form "reach high score X with perk A,B,C but without perk B,C,D"
-- remove loop mode :
- - remove basecombo
- - remove mode
- - clear old runs in other mode
-- ignore scores in creative mode
-- remove the slow mode
-- adjusted the light effects
-- added white border around dark grey bricks
-- remove the opaque coin options, all coins are opaque, but dark grey ones have white border
-- archive each version as an html file and apk
-- publish 29062687 on play store
-- redo video
-- review fastlane text
-
-- tried and cancelled native desktop app build with tauri because :
- - there's no cross compilation, so no exe build on linux
- - you need to sign executable differently for each platform
- - the .deb and .rmp files were 3.8M for a 0.1M app
- - the appimage was crazy big (100M)
- - I'd need a mac to make a mac version that probably wouldn't run without doing the app store dance with apple
-
-## 29062687
-
-- tried and cancelled webgl rendering
- - it's a lot of code
- - i'm not great at it
- - it requires a significant rewrite
- - for most things, no perf difference
- - the main goal of having more colorful backgrounds can be achieved by running the lights layer at lower res
-- "Miss warning" option is now on by default (ball's particles are red if catching it would be a "miss")
-- "Show +X in gold" option is now on by default (show a +X when combo increases)
-- "High contrast" option added, off by default (applies lights layer again as "soft light" at the end of the render)
-- "Colorful coins" option now applied at render time instead of coin spawn time, to make preview easier
-- when settings are opened on pc, they show up on the side and the overlay is transparent to let you preview the changes
-
-## 29062545
-
-- Perks list now only lists upgrades that have been picked, or have banned levels
-- After clearing a level, that level is dimmed in the clairvoyant level list [Bearded-Axe]
-- limited clairvoyant to level one outside looped runs [obigre]
-- yoyo now has more effect when the ball is at the top of the screen [obigre]
-- telekinesis now has more effect when the ball is at the bottom of the screen
-- "Top is lava" combo lost text is now spawned a bit lower to be more visible [obigre]
-
-## 29061838
-
-- New perk : Fountain toss [colin] - loosing coins makes your combo grow
-- Boosted : Asceticism now decreases combo instead of resetting it
-- Graphics : show respawn particles even in basic mode [obigre]
-- Graphics : adjusted the brightness of the game a bit more
-
-## 29061490
-
-- Graphics : option to add more light (on by default)
-- Graphics : option to make coins more readable (on by default)
-- Graphics : background light effects optimization
-- Graphics : all levels background have been checked (4 buggy ones removed) and will be assigned randomly
-- Fixed : display gained combo was showing +0 sometimes
-
-## 29060272
-
-- Fixed: Strict sample size was counting destroyed bricks, now count hits as explained in the help
-- Fixed: passive_income was resetting your combo if you moved around the end of the last level
-- Fixed: a high score issues was systematically erasing the high score in the web version, i added a migration to load the best score for your top games to recover the high score.
-- QOL: option to display gained combo as onscreen text
-- QOL: publish an apk to itch.io with every build
-- Internal: added a simple game data migration system
-
-## 29059721
-
-- QOL: icons in settings menu
-- QOL: choose starting perks
-- QOL: fixed issue with reloading with [R] key
-- QOL: gameover screen restarts in the same game mode
-- Fixed: Trampoline render sides in red.
-- Fixed: tooltips stuck on mobile
-- Fixed: issues with restarting a game with fullscreen on
-
-## 29058981
-
-- [jaceys] A visual indication of whether a ball has hit a brick this serve (as an option)
-- Top down /reach: now only the lowest level of N bricks resets combo, and all other bricks do +N combo
-- picky eater: don't reset if no brick of ball color
-- main menu : show high score
-- keep high score of past runs
-- tooltip on stats
-- fixed : looping didn't work
-- two abstract levels, stripes and openings
-- added reset button for perks in lab mode
-
-## 29058469
-
-- New game mode : loop / long game
- - the goal is to build many different build centered on one perk
- - At the end of level 7, you get to restart at level 1 for 6 levels.
- - all your perks are banned except one
- - The perk you keep is leveled up, and can be leveled up a second time during the next loop
- - the perks you don't keep are "banned", meaning their max level is reduced by as many levels as you had picked
- - unlocked after unlocking all perks
-- New game mode : lab / creative
- - the goal is to come up with 3 completely different but powerful play styles
- - you freely create 3 builds from all the perks level available
- - you play them against the levels of your choice
- - try to make as much score as possible in total
- - unlocked after unlocking all perks
-- New levels :
- - Pingwin
- - Sunglasses
- - Balloon
-- Adjusted levels :
- - orca is no longer made of bombs, but gray block
-- New perks
- - addiction : reward faster gameplay
-- Adjusted perks
- - Hot start : 30 combo per level instead of 15
- - Telekinesis: limited to level 1
- - Asceticism now gives +3 combo per lvl
- - Fortunate ball has a stronger effect
- - Bigger puck : puck can now cover the whole screen at higher levels, but not more
- - Corner shot : higher levels let you move further away from the play area
- - Forgiving : level 2 halves the penalty, level 3 is a third ..
- - Helium : stronger anti gravity at higher levels
- - Implosions : works like bigger-explosions at higher levels
- - Metamorphosis : coins can stain more bricks at higher levels
- - Re-spawn : now delay based and probabilistic, to scale more easily with higher levels. no need to hit the puck
- - sacrifice : at level 2+ the combo is doubles/tripled just before clearing the screen of any bricks
- - shunt : changed the math keep 25% of combo at level 1,50% at level 2,63% at level 3,70% at level 4..
- - soft reset : same math as shunt
- - smaller puck : now the puck can get as small as a ball
- - Unbounded : at level 2+, the top of the level is gone too
- - concave_puck : ball bounces straighter and straighter, to the point where you can't move it without another perk
- - shocks lvl 2+ make bigger explosions
- - trampoline: nerfed a little bit, now all sides and top hit reduce combo
-
-- Quality of life
- - Updated discord invite link that had expired
- - Full screen is now a persistent option, when it's on the game will switch to full screen before starting
- - Added an option to always get colored coins
- - Made the "combo lost" text last 500ms instead of the pointless 150ms
- - Added in-game help and credits, which can be translated
- - Balancing : you earn an extra perk when playing well, and a reroll when playing perfectly
- - added a prominent "donate" link after 5h of playing, and setting to hide it permanently
- - disabled auto-release to F-Droid, i'll use the web version as the testing ground first
- - added a white border around all coins, to make dark ones visible on dark bg
- - [jaceys] counters for coins lost, misses, and boundary bounces, as well as a timer.
- - Unlocked list : split perk and levels, added tooltips
-
-## 29049575
-
-- added rerolls
-- Sacrifice : clear screen instead of doubling coins
-
-## 29048147
-
-- Ascetism : render coins with red border if there's a combo
-- Warn about unbounded
-- Red border dashes
-
-# Ideas and features
-
-## Easy perk ideas
-
-- chill : no perks gain, no level limit,+20 base combo
-- when the ball teleport, probability that it's duplicated instead
-- combo resets on teleport
-- combo resets when hitting puck without a teleport
-- teleport ball to puck as soon as it hits something (% chance)
-- allow dropping balls that are about to miss.
-- square coins : coins loose all horizontal momentum when hitting something.
-- ball turns following puck motion
-- "+1 coin for each ball within a small radius of the broken brick" ?
-- two for one : add a 2 for one upgrade combo to the choice lists
-- cash out : double last level's gains
-- snowball : Combo resets every 0.1s . +1 combo for each combo gained Since last reset.
-- Chain reaction : +lvl*lvl combo per brick broken by an explosion, combo resets after explosion is over
-- catching a coin changes the color of the balls
-- coins stained by balls
-- fast pause : pause delay divided by {{lvl}} (helps with teleport)
-- [colin] Capital - les vies non perdues à la fin du niveau rapportent un bonus de points
-- ban 3 random perks from pool, gain 2 upgrades
-- faster coins, double value
-- balls repulse coins
-- n% of coins missed respawn at the ball
-- +1 combo per brick broken after a wall bounce, reset otherwise
-- combo climbs by 1 every 2 second, unless no coin was caught, then it resets
-- [colin] golden corners - catch coins at the sides of the puck to double their value
-- [colin] varied diet - your combo grows by 2 when your ball changes color, but decreses by one when a brick is broken ?
-- [colin] trickle up - inverse of reach more or less
-- +lvl combo per bricks / resets after 5/lvl seconds without explosion ?
-- +lvl combo per bricks / resets after 5/lvl seconds without coin catch ?
-- +lvl combo per bricks / resets after 5/lvl seconds without ball color change ?
-- +lvl combo per bricks / resets after 5/lvl seconds without sides hit ?
-- + lvl x n combo when destroying a brick after bouncing on a side/top n times ?
-- make stats a clairvoyant thing
-- [colin]P ocket money — bricks absorb coins that touch them, which are released on brick destruction (with a bonus?)
-- [colin] turn ball gravity on after a top bar hit, and until bouncing on puck
-- fan : paddle motion creates upward draft that lifts coins and balls
-
-## Medium difficulty perks ideas
-- coins combine when they hit (into one coin with the sum of the values, but need a way to represent that)
-- balls collision split them into 4 smaller balls, lvl times (requires rework)
-- offer next level choice after upgrade pick
-- [colin] mirror puck - a mirrored puck at the top of the screen follows as you move the bottom puck. it helps with keeping combos up and preventing the ball from touching the ceiling. it could appear as a hollow puck so as to not draw too much attention from the main bottom puck.
-- [colin] Combos extrêmes: lvl2 pour tous les combos, qui fait que le combo rapporte double ou triple, mais si sur un niveau la condition n'est pas respectée alors le perk ne donne plus de combo bonus pour ce niveau.
-- [colin] Mytosis - les blocs bombe n'explosent pas mais relâchent une nouvelle balle à la place (clashes with "shocks" and "sapper")
-- [colin] Juggle - au début du niveau, chaque balle est lancée l'une après au lieu de toutes à la fois (needs some work)
-- SUPER HOT (time moves when puck moves)
-- bricks attract ball
-- bricks attract coins
+## Perk ideas
- wrap left / right
-- correction : pick one past upgrade to remove and replace by something else
-- +1 combo when ball goes downward, reset if upward
-- 2x speed after bouncing on puck
-- the more balls are close to a brick, the more combo is gained when breaking it. If only one ball, loose one point or reset
-- ball avoids brick of wrong color
-- puck slowly follows desired position, but +1 combo
-- knockback : hitting a brick pushes it (requires sturdy bricks)
-
-## Hard perk ideas
+- n% of the broken bricks respawn when the ball touches the puck
+- bricks take twice as many hits but drop 50% more coins
+- wind (puck positions adds force to coins and balls)
+- balls repulse coins
+- n% of coins missed respawn at the top
+- lightning : missing triggers and explosive lighting strike around ball path
+- coins repulse coins (could get really laggy)
+- balls repulse coins
+- balls attract coins
+- twice as many coins after a wall bounce, twice as little otherwise ?
+- fusion reactor (gather coins in one spot to triple their value)
+- missing makes you loose all score of level, but otherwise multiplier goes up after each breaking
+- soft reset, cut combo in half instead of zero
+- missile goes when you catch coin
+- missile goes when you break a brick
+- puck bounce +1 combo, hit nothing resets
+- multiple hits on the same brick (show remaining resistance as number)
+- bricks attract ball
+- replay last level (remove score, restores lives if any, and rebuild )
- accelerometer controls coins and balls
-- [colin] side pucks - same as above but with two side pucks : hard to know where to put them
-- [colin] Perk: second puck in the middle of the screen
-- [colin] Sponge Ball : the ball stores coins it collides with, and releases them when bouncing on any border (left, right, top).
+- bricks attract coins
+- breaking bricks stains neighbours
+- extra kick after bouncing on puck
+- transparent coins
+- coins of different colors repulse
+- bricks follow game of life pattern with one update every second
+- 2x coins when ball goes downward / upward, half that amount otherwise ?
+## Engine ideas
-## ideas to sort
-- wind : move coins based on puck movement not position
-- double coin value when they hit the sides
-- [colin]Brambles — coins that touch the walls and ceiling get stuck and are thrown back when the last brick is destroyed
-- [colin]Ball of Greed — the ball can collect coins (might be worth dividing into levels: lvl 1, can collect coins only after two bounces on bricks or walls. lvl 2, can collect after 1 bounce. lvl 3, can collect coins anytime)(or change the ball collection radius as the level grows)
-- [colin]Phantom ball — the ball phases through 2 bricks then becomes solid (lvl2: through 6 bricks, lvl3; through all bricks until it touches a wall)
-- [colin]Cryptomoney — coins that should be generated by bricks are instantly collected, but count for half their value
-- [colin]Relative time — ball speed depends on its position: if it's high up on thi screen it's fast, if it's lower it's slower
+- show total score on end screen (score added to total)
+- show stats on end screen compared to other runs
+- handle back bouton in menu
+- Make a small mp4/gif of game which can be shown on gameover and shared. https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
+- mouvement relatif du puck
+- balls should collide with each other
+- when game resumes near bottom, be unvulnerable for .5s ? , once per level
+- apply global curve / brightness to canvas when things blow, or just always to make neon effect better
+- manifest for PWA (android and apple)
+- lights shadows
+- keyboard support
+- Offline mode web for iphone
+- webgl rendering
-- ball attracted by bricks of the color of the ball
-- level flips horizontally every time a ball bounces on puck
-- [colin] close quarters - balle attirée par tous les blocs/par un bloc aléatoire, actif à portée de bloc (+1bloc au lvlup)/proportionnel à une force (+puissance au lvlup)…
-- [colin] plusieurs perks qui déclenchent des effets quand une balle est perdue. par ex: +3 combo à chaque balle perdue, 5 blocs transformés en bombe, balle et coins ralentis, blocs régénérés…
-- [colin] faster style - augmente le combo en fonction de la vitesse de la balle
-- [colin] perk: roulette - gagne instantanément 2 perks aléatoires
-- other block types : bumper (speed up ball) [colin], metal (can't break) [nicolas]
-- flip perk
+## Level ides
-## extra levels
-
-- Good games :
- - FTL
- - Nova drift
- - Noita
- - Enter the gungeon
- - Zero Sivert
- - Factorio
- - Swarm
- - Nuclear throne
- - Brigador
-
-
-- letters and an associated word or name
-- famous characters and movies
-- famous places : eiffel tower, taj mahal, etc..
+- famous games
+- letters
- fruits
- animals
-- countries flags and shapes
-## UX / gameplay
+## Credits
-- make menu and score button more "button like" when you just installed the game.
-- avoid showing a +1 and -1 at the same time when a combo increase is reset
-- explain to iOS users how to add the app to home screen to get fullscreen
-- delayed start on mobile to let users place the puck where they want
-- experiment with showing the combo somewhere else, maybe top center, maybe instead of score.
-- display a multiplicator if it's not 100%, have some perks add to it
+I pulled many background patterns from https://pattern.monster/
+They are displayed in [patterns.html](patterns.html) for easy inclusion.
+Some of the sound generating code was written by ChatGPT, and heavily
+adapted to my usage over time.
-## Game engine features ideas
-- add a clickable button to allow sound to play in chrome android
-- save state in localstorage for easy resume of a game in progress
-- handle back bouton in menu
-- Offline mode web for iphone
-- controller support on web/mobile
-- leaderboard for not using each perk, like "best runs without hot start"
+Some of the pixel art is taken from google image search results, I hope to replace it by my own over time :
+[Heart](https://www.youtube.com/watch?v=gdWiTfzXb1g)
+[Mushroom](https://pixelartmaker.com/art/cce4295a92035ea)
-## Maybe one day
-- https://weblate.org/fr/ quite annoying to have merge conflicts while pushing, i'll enable it later.
-- auto-detect device performance at first startup and adjust settings accordingly (hard to do in any sort of useful way)
-- [jaceys] Move the restart button out of the menu, so that it is more easily accessible (will allow user to choose starting perk instead)
-- colored coins only (coins should be of the color of the ball to count, otherwise what ? i'd rather avoid negative points)
-- coins avoid ball of different color (pointless)
-- [colin] wormhole - the puck sometimes don't bounce the ball back up but teleports it to the top of the screen as if it fell through from bottom to top. higher levels reduce the times it takes to reload that effect (not sure how that to word that in 1 setence)
-- [colin] Mental charge - the puck is divided into two smaller pucks, then 3 smaller ones at lvl 2 : what's the point ?
-- [colin] sturdy ball - does more damage to bricks, to conter sturdy bricks :that's pierce now
-- [colin] plot - plot the ball's trajectory as you position your puck : too hard when you add other perks
-- [colin] piggy bank - bricks absorb coins that fall onto it, and release them back as they are broken, with added value : equivalent to Asceticism
-- [colin] ball coins - coins share the same physics as coins and bounce on walls and bricks : really hard to balance with speeds and all
-- non brick-shaped bricks, tilted bricks,moving blocks : very difficult because of engine optimisations
-- 3 random perks immediately, or maybe "all level get twice as many upgrades, but they are applied randomly, and you aren't told which ones you have."
-- coins repulse coins, could get really laggy ?
-- russian roulette: 5/6 chances to get a free upgrade, 1/6 chance of game over. Not really fun
-- [colin] bigger ball - self-explanatory, or is it ? what's the point ? physics would break now if ball bigger than bricks
-- [colin] smaller ball - doable, but why
-- [colin] earthquake - when the puck hits any side of the screen with velocity, the screen shakes and a brick explodes/falls from the level. alternatively, any brick you catch with the puck gives you the coins at the current combo rate. each level lowers the amount of hits before a brick falls. Problem : no limit on how often you can slam the puck around
-- missile goes when you catch coin
-- missile goes when you break a brick
-- [colin] Batteries - lvl1: recharge les pouvoirs du puck quand la balle touche le haut de l'écran (1 fois par lancer, se recharge en touchant le puck). lvl2: également après voir détruit 6 blocs. lvl3: également quand elle touche les bords de l'écran : i'll probably just let the second puck replace this
- - store much more details about run (level by level) as numbers only (instead of json that gets big false)
-- [colin] hitman - hit the marked brick for +5 combo. each level increases the combo you get for it.
-- [colin] sweet spot - place your puck directly below a moving spot at the top of the level to increase your combo
-- [colin] reward the player with more choices/perks for breaking a brick while having reached an increasing combo thresholds. 5 combo, then 10, then 20, then 40 etc… once a threshold is reached you aren't rewarded for that threshold again until you start a rew run
-- mobile option: relative movement of the touch would be amplified and added to the puck
-- mobile option: don't pause on mobile when lifting finger
-- translate fastlane presentation texts to french
-- convert captures to mp4 unsing ffmpeg wasm because reddit refuses webm files
-- disable zooming (for ios double tap)
-- Waterline under the puck, coins slow down a lot, reflections
-- webgl rendering: background gradient light map, shinier coins, quite hard
-- on mobile, add an element that feels like it can be "grabbed" and make it shine while writing "Push here to play"
-- hard mode : bricks take many hits, perks more rare, missing clears level score, missing coins deducts score..
-- architect mode :
- - play 7 levels, each with a different build.
- - Perk levels can only be used once, so if you take one for level 1, you won't have it to level 2-7.
- - Your final score is your worst score times your best score
- - You'll see the levels in advance
-- stats by lack of perk, like "best score without using hot start".
-- split screen multiplayer
-- Add color schemes into the game (ex : Catppuccin, Dracula, Terminal, etc)
-- final bosses (large vertical level that scrolls down faster and faster)
-- add loop run where user levels can't be used in further loops (boring)
-- add lab mode where you need to make three builds (complex, lots of clicking, not fun)
-
-# Credits
-
-I pulled the background patterns from https://pattern.monster/
-
-I wanted an APK to start in fullscreen and be able to list it on fdroid and the play store. I started with an empty view and went to work trimming it down, with the help of that tutorial : https://github.com/fractalwrench/ApkGolf/blob/master/blog/BLOG_POST.md
-
-Colin (obigre) brought a lot of fantastic ideas to the game, here's his website (in French) : https://colin-crapahute.bearblog.dev/
-
-# How to install
-
-Breakout 71 can be installed and work offline in many ways:
-
-- Download an index.html file from [itch.io](https://renanlecaro.itch.io/breakout71) to play offline on your computer (latest version always)
-- Download the latest apk from [itch.io](https://renanlecaro.itch.io/breakout71) to play offline on your android phone (latest version always)
-- Add [the app](https://breakout.lecaro.me/) to your home screen on android, and it should play even when offline thanks to the service workers (latest version always)
-- Install the latest version from the play store : https://play.google.com/store/apps/details?id=me.lecaro.breakout (updated from time to time)
-- Install the latest version from Fdroid : https://f-droid.org/packages/me.lecaro.breakout/ (updated very rarely because of the updates publication lag)
-- Download the index.html file or apk from my archive server : https://archive.lecaro.me/public-files/b71/ (any version including latests)
-
-# System requirements
-
-The game should perform well even on low-end devices. It's very lean and does not take much storage space (Roughly 0.1MB). The web version is supposed to work on iOS safari, Firefox ESR and chrome, on desktop and mobile.
-If the app stutters, turn on "fast mode" in the settings to render a simplified view that should be faster. You can adjust many aspects of the game there, go have a look !
-
\ No newline at end of file
+I wanted an APK to start in fullscreen and be able to list it on fdroid and the play store. I started with an empty view and went to work trimming it down, with the help of that tutorial
+https://github.com/fractalwrench/ApkGolf/blob/master/blog/BLOG_POST.md
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 082a474..e5d1b10 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,27 +1,9 @@
-import java.util.Properties
-import java.io.FileInputStream
-
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
}
-
-val keystorePropertiesFile = rootProject.file("keystore.properties")
-val keystoreProperties = Properties()
-keystoreProperties.load(FileInputStream(keystorePropertiesFile))
-
-
android {
- signingConfigs {
- create("release") {
- keyAlias = keystoreProperties["keyAlias"] as String
- keyPassword = keystoreProperties["keyPassword"] as String
- storeFile = file(keystoreProperties["storeFile"] as String)
- storePassword = keystoreProperties["storePassword"] as String
- }
- }
-
namespace = "me.lecaro.breakout"
compileSdk = 34
@@ -29,8 +11,8 @@ android {
applicationId = "me.lecaro.breakout"
minSdk = 21
targetSdk = 34
- versionCode = 29106448
- versionName = "29106448"
+ versionCode = 28999417
+ versionName = "28999417"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
@@ -45,7 +27,7 @@ android {
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
- signingConfig = signingConfigs.getByName("release")
+ signingConfig = signingConfigs.getByName("debug")
}
}
compileOptions {
@@ -67,6 +49,22 @@ android {
}
}
}
-dependencies {
- implementation(libs.androidx.core)
-}
+
+//dependencies {
+//
+// implementation(libs.androidx.core.ktx)
+// implementation(libs.androidx.lifecycle.runtime.ktx)
+// implementation(libs.androidx.activity.compose)
+// implementation(platform(libs.androidx.compose.bom))
+// implementation(libs.androidx.ui)
+// implementation(libs.androidx.ui.graphics)
+// implementation(libs.androidx.ui.tooling.preview)
+// implementation(libs.androidx.material3)
+// testImplementation(libs.junit)
+// androidTestImplementation(libs.androidx.junit)
+// androidTestImplementation(libs.androidx.espresso.core)
+// androidTestImplementation(platform(libs.androidx.compose.bom))
+// androidTestImplementation(libs.androidx.ui.test.junit4)
+// debugImplementation(libs.androidx.ui.tooling)
+// debugImplementation(libs.androidx.ui.test.manifest)
+//}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7e787ff..2700098 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
+
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/assets/game.js b/app/src/main/assets/game.js
new file mode 100644
index 0000000..5dcb2b9
--- /dev/null
+++ b/app/src/main/assets/game.js
@@ -0,0 +1,2546 @@
+const MAX_COINS = 400;
+const canvas = document.getElementById("game");
+let ctx = canvas.getContext("2d", {alpha: false});
+
+let ballSize = 20;
+const coinSize = Math.round(ballSize * 0.8);
+const puckHeight = ballSize;
+
+if (allLevels.find(l => l.focus)) {
+ allLevels = allLevels.filter(l => l.focus)
+}
+// Used to render perk icons
+const perkIconsLevels = {}
+allLevels = allLevels.filter(l => {
+ if (l.name.startsWith('perk:')) {
+ perkIconsLevels[l.name.split(':')[1]] = l
+ return false
+ }
+ return true
+})
+allLevels.forEach((l, li) => {
+ l.threshold = li < 8 ? 0 : Math.round(Math.min(Math.pow(10, 1 + (li + l.size) / 30)* 10, 10000) * (li))
+ l.sortKey = (Math.random()+3)/3.5 * l.bricks.filter(i=>i).length
+})
+
+let runLevels = []
+
+let currentLevel = 0;
+
+const bombSVG = document.createElement('img')
+bombSVG.src = 'data:image/svg+xml;base64,' + btoa(`
+
+ `);
+
+
+// Whatever
+let puckWidth = 200;
+const perks = {};
+
+let baseSpeed = 12; // applied to x and y
+let combo = 1;
+
+function baseCombo() {
+ return 1 + perks.base_combo * 3;
+}
+
+function resetCombo(x, y) {
+ const prev = combo;
+ combo = baseCombo();
+ if (!levelTime) {
+ combo += perks.hot_start * 15;
+ }
+ if (prev > combo && perks.soft_reset) {
+ combo += Math.floor((prev - combo) / (1 + perks.soft_reset))
+ }
+ const lost = Math.max(0, prev - combo);
+ if (lost) {
+ incrementRunStatistics('combo_resets', 1)
+ for (let i = 0; i < lost && i < 8; i++) {
+ setTimeout(() => sounds.comboDecrease(), i * 100);
+ }
+ if (typeof x !== "undefined" && typeof y !== "undefined") {
+ flashes.push({
+ type: "text",
+ text: "-" + lost,
+ time: levelTime,
+ color: "red",
+ x: x,
+ y: y,
+ duration: 150,
+ size: puckHeight,
+ });
+ }
+ }
+}
+
+function decreaseCombo(by, x, y) {
+ const prev = combo;
+ combo = Math.max(baseCombo(), combo - by);
+ const lost = Math.max(0, prev - combo);
+
+ if (lost) {
+ sounds.comboDecrease();
+ if (typeof x !== "undefined" && typeof y !== "undefined") {
+ flashes.push({
+ type: "text",
+ text: "-" + lost,
+ time: levelTime,
+ color: "red",
+ x: x,
+ y: y,
+ duration: 300,
+ size: puckHeight,
+ });
+ }
+ }
+}
+
+let gridSize = 12;
+
+let running = false, puck = 400;
+
+function play() {
+ if (running) return
+ running = true
+ if (audioContext) {
+ audioContext.resume()
+ }
+}
+
+function pause() {
+ if (!running) return
+ running = false
+ needsRender = true
+ if (audioContext) {
+ setTimeout(() => {
+ if (!running)
+ audioContext.suspend()
+ }, 1000)
+ }
+}
+
+let offsetX, offsetXRoundedDown, gameZoneWidth, gameZoneWidthRoundedUp, gameZoneHeight, brickWidth, needsRender = true;
+
+const background = document.createElement("img");
+const backgroundCanvas = document.createElement("canvas");
+background.addEventListener("load", () => {
+ needsRender = true
+})
+
+const fitSize = () => {
+ const {width, height} = canvas.getBoundingClientRect();
+ canvas.width = width;
+ canvas.height = height;
+ backgroundCanvas.width = width;
+ backgroundCanvas.height = height;
+
+
+ gameZoneHeight = isSettingOn("mobile-mode") ? (height * 80) / 100 : height;
+ const baseWidth = Math.round(Math.min(canvas.width, gameZoneHeight * 0.73));
+ brickWidth = Math.floor(baseWidth / gridSize / 2) * 2;
+ gameZoneWidth = brickWidth * gridSize;
+ offsetX = Math.floor((canvas.width - gameZoneWidth) / 2);
+ offsetXRoundedDown = offsetX
+ if (offsetX < ballSize) offsetXRoundedDown = 0
+ gameZoneWidthRoundedUp = width - 2 * offsetXRoundedDown
+ backgroundCanvas.title = 'resized'
+ // Ensure puck stays within bounds
+ setMousePos(puck);
+ coins = [];
+ flashes = [];
+ pause()
+ putBallsAtPuck();
+};
+window.addEventListener("resize", fitSize);
+
+function recomputeTargetBaseSpeed() {
+ // We never want the ball to completely stop, it will move at least 3px per frame
+ baseSpeed = Math.max(3,gameZoneWidth / 12 / 10 + currentLevel / 3 + levelTime / (30 * 1000) - perks.slow_down * 2);
+}
+
+
+function brickCenterX(index) {
+ return offsetX + ((index % gridSize) + 0.5) * brickWidth;
+}
+
+function brickCenterY(index) {
+ return (Math.floor(index / gridSize) + 0.5) * brickWidth;
+}
+
+function getRowCol(index) {
+ return {
+ col: index % gridSize, row: Math.floor(index / gridSize),
+ };
+}
+
+function getRowColIndex(row, col) {
+ if (row < 0 || col < 0 || row >= gridSize || col >= gridSize) return -1;
+ return row * gridSize + col;
+}
+
+
+function spawnExplosion(count, x, y, color, duration = 150, size = coinSize) {
+ if (!!isSettingOn("basic")) return;
+ for (let i = 0; i < count; i++) {
+
+ flashes.push({
+ type: "particle",
+ time: levelTime,
+ size,
+ x: x + ((Math.random() - 0.5) * brickWidth) / 2,
+ y: y + ((Math.random() - 0.5) * brickWidth) / 2,
+ vx: (Math.random() - 0.5) * 30,
+ vy: (Math.random() - 0.5) * 30,
+ color,
+ duration:150
+ });
+ }
+}
+
+
+
+let score = 0;
+let scoreStory = [];
+
+let lastexplosion = 0;
+let highScore = parseFloat(localStorage.getItem("breakout-3-hs") || "0");
+
+let lastPlayedCoinGrab = 0
+
+function addToScore(coin) {
+ coin.destroyed = true
+ score += coin.points;
+ addToTotalScore(coin.points)
+ if (score > highScore && !hadOverrides) {
+ highScore = score;
+ localStorage.setItem("breakout-3-hs", score);
+ }
+ if (!isSettingOn('basic')) {
+ flashes.push({
+ type: "particle",
+ duration: 100 + Math.random() * 50,
+ time: levelTime,
+ size: coinSize / 2,
+ color: coin.color,
+ x: coin.previousx,
+ y: coin.previousy,
+ vx: (canvas.width - coin.x) / 100,
+ vy: -coin.y / 100,
+ ethereal: true,
+ })
+ }
+
+ if (Date.now() - lastPlayedCoinGrab > 16) {
+ lastPlayedCoinGrab = Date.now()
+ sounds.coinCatch(coin.x)
+ }
+ incrementRunStatistics('caught_coins', coin.points)
+
+}
+
+let balls = [];
+
+function resetBalls() {
+ const count = 1 + (perks?.multiball || 0);
+ const perBall = puckWidth / (count + 1);
+ balls = [];
+ for (let i = 0; i < count; i++) {
+ const x = puck - puckWidth / 2 + perBall * (i + 1);
+ balls.push({
+ x,
+ previousx: x,
+ y: gameZoneHeight - 1.5 * ballSize,
+ previousy: gameZoneHeight - 1.5 * ballSize,
+ vx: Math.random() > 0.5 ? baseSpeed : -baseSpeed,
+ vy: -baseSpeed,
+ sx: 0,
+ sy: 0,
+ color: currentLevelInfo()?.black_puck ? '#000' : "#FFF",
+ hitSinceBounce: 0,
+ piercedSinceBounce: 0,
+ sparks: 0,
+ });
+ }
+}
+
+function putBallsAtPuck() {
+ const count = balls.length;
+ const perBall = puckWidth / (count + 1);
+ balls.forEach((ball, i) => {
+ const x = puck - puckWidth / 2 + perBall * (i + 1);
+ Object.assign(ball, {
+ x,
+ previousx: x,
+ y: gameZoneHeight - 1.5 * ballSize,
+ previousy: gameZoneHeight - 1.5 * ballSize,
+ vx: Math.random() > 0.5 ? baseSpeed : -baseSpeed,
+ vy: -baseSpeed,
+ sx: 0,
+ sy: 0,
+ });
+ });
+}
+
+resetBalls();
+// Default, recomputed at each level load
+let bricks = [];
+let flashes = [];
+let coins = [];
+let levelStartScore = 0;
+let levelMisses = 0;
+let levelSpawnedCoins = 0;
+
+function getLevelStats() {
+ const catchRate = (score - levelStartScore) / (levelSpawnedCoins || 1);
+
+ let repeats = 1;
+ let choices = 3;
+
+ let timeGain = '', catchGain = '', missesGain = ''
+ if (levelTime < 30 * 1000) {
+ repeats++;
+ choices++;
+ timeGain = " (+1 upgrade)"
+ } else if (levelTime < 60 * 1000) {
+ choices++;
+ timeGain = " (+1 choice)"
+ }
+ if (catchRate === 1) {
+ repeats++;
+ choices++;
+ catchGain = " (+1 upgrade)"
+ } else if (catchRate > 0.9) {
+ choices++;
+ catchGain = " (+1 choice)"
+ }
+ if (levelMisses === 0) {
+ repeats++;
+ choices++;
+ missesGain = " (+1 upgrade)"
+ } else if (levelMisses <= 3) {
+ choices++;
+ missesGain = " (+1 choice)"
+ }
+
+ let stats = `
+ You caught ${score - levelStartScore} coins ${catchGain} out of ${levelSpawnedCoins} in ${Math.round(levelTime / 1000)} seconds${timeGain}.
+ You missed ${levelMisses} times ${missesGain}.
+ `;
+
+
+ let text = [stats];
+
+ return {
+ stats, text: text.map(t => '
' + t + '
').join('\n'), repeats, choices,
+ };
+}
+
+function pickedUpgradesHTMl() {
+ return upgrades.filter(u => perks[u.id]).map(u => u.icon).join(' ')
+}
+
+async function openUpgradesPicker() {
+ let {text, repeats, choices} = getLevelStats();
+ scoreStory.push(`Finished level ${currentLevel + 1} (${currentLevelInfo().name}): ${text}`,);
+
+ while (repeats--) {
+ const actions = pickRandomUpgrades(choices);
+ if (!actions.length) break
+ let textAfterButtons=`Upgrades picked so far :
${pickedUpgradesHTMl()}
`;
+
+ const cb = await asyncAlert({
+ title: "Pick an upgrade " + (repeats ? "(" + (repeats + 1) + ")" : ""), actions, text, allowClose: false,
+ textAfterButtons
+ });
+ cb();
+ }
+ resetCombo();
+ resetBalls();
+}
+
+function setLevel(l) {
+ pause()
+ if (l > 0) {
+ openUpgradesPicker().then();
+ }
+ currentLevel = l;
+
+ levelTime = 0;
+ lastTickDown = levelTime;
+ levelStartScore = score;
+ levelSpawnedCoins = 0;
+ levelMisses = 0;
+
+ resetCombo();
+ recomputeTargetBaseSpeed();
+ resetBalls();
+
+ const lvl = currentLevelInfo();
+ if (lvl.size !== gridSize) {
+ gridSize = lvl.size;
+ fitSize();
+ }
+ incrementRunStatistics('lvl_size_' + lvl.size, 1)
+ incrementRunStatistics('lvl_name_' + lvl.name, 1)
+ coins = [];
+ bricks = [...lvl.bricks];
+ flashes = [];
+
+ background.src = 'data:image/svg+xml;base64,' + btoa(lvl.svg)
+
+}
+
+function currentLevelInfo() {
+ return runLevels[currentLevel % runLevels.length];
+}
+
+function reset_perks() {
+
+ for (let u of upgrades) {
+ perks[u.id] = 0;
+ }
+
+ if (nextRunOverrides.perks) {
+ const first = Object.keys(nextRunOverrides.perks)[0]
+ Object.assign(perks, nextRunOverrides.perks)
+ nextRunOverrides.perks = null
+ return first
+ }
+
+ const giftable = getPossibleUpgrades().filter(u => u.giftable)
+ const randomGift = isSettingOn('easy') ? 'slow_down' : giftable[Math.floor(Math.random() * giftable.length)].id;
+ perks[randomGift] = 1;
+
+ return randomGift
+}
+
+const upgrades = [
+ {
+ "threshold": 0,
+ "id": "extra_life",
+ "name": "+1 life",
+ "max": 7,
+ "help": "Survive dropping the ball once."
+ },
+ {
+ "threshold": 0,
+ "id": "streak_shots",
+ "giftable": true,
+ "name": "Single puck hit streak",
+ "max": 1,
+ "help": "Break many bricks at once."
+ },
+
+ {
+ "threshold": 0,
+ "id": "base_combo",
+ "giftable": true,
+ "name": "+3 base combo",
+ "max": 7,
+ "help": "Your combo starts 3 points higher."
+ },
+ {
+ "threshold": 0,
+ "id": "slow_down",
+ "name": "Slower ball",
+ "max": 2,
+ "help": "Slows down the ball."
+ },
+ {
+ "threshold": 0,
+ "id": "bigger_puck",
+ "name": "Bigger puck",
+ "max": 2,
+ "help": "Catches more coins."
+ },
+ {
+ "threshold": 0,
+ "id": "viscosity",
+ "name": "Slower coins fall",
+ "max": 3,
+ "help": "Coins quickly decelerate."
+ },
+ {
+ "threshold": 0,
+ "id": "sides_are_lava",
+ "giftable": true,
+ "name": "Shoot straight",
+ "max": 1,
+ "help": "Avoid the sides for more coins."
+ },
+ {
+ "threshold": 0,
+ "id": "top_is_lava",
+ "giftable": true,
+ "name": "Sky is the limit",
+ "max": 1,
+ "help": "Avoid the top for more coins."
+ },
+ {
+ "threshold": 0,
+ "id": "skip_last",
+ "name": "Last brick breaks",
+ "max": 7,
+ "help": "The last brick will self-destruct."
+ },
+ {
+ "threshold": 500,
+ "id": "telekinesis",
+ "giftable": true,
+ "name": "Puck controls ball",
+ "max": 2,
+ "help": "Control the ball's trajectory."
+ },
+ {
+ "threshold": 1000,
+ "id": "coin_magnet",
+ "name": "Puck attracts coins",
+ "max": 3,
+ "help": "Coins are drawn toward the puck."
+ },
+ {
+ "threshold": 1500,
+ "id": "multiball",
+ "giftable": true,
+ "name": "+1 ball",
+ "max": 3,
+ "help": "Start with one more balls."
+ },
+ {
+ "threshold": 2000,
+ "id": "smaller_puck",
+ "name": "Smaller puck",
+ "max": 2,
+ "help": "Gives you more control."
+ },
+ {
+ "threshold": 3000,
+ "id": "pierce",
+ "giftable": true,
+ "name": "Ball pierces bricks",
+ "max": 3,
+ "help": "Destroy 3 blocks before bouncing."
+ },
+ {
+ "threshold": 4000,
+ "id": "picky_eater",
+ "giftable": true,
+ "name": "Single color streak",
+ "color_blind_exclude": true,
+ "max": 1,
+ "help": "Break bricks color by color."
+ },
+ {
+ "threshold": 5000,
+ "id": "metamorphosis",
+ "name": "Coins stain bricks",
+ "color_blind_exclude": true,
+ "max": 1,
+ "help": "Coins color the bricks they touch."
+ },
+ {
+ "threshold": 6000,
+ "id": "catch_all_coins",
+ "giftable": true,
+ "name": "Compound interest",
+ "max": 3,
+ "help": "Avoid missing coins with your puck."
+ },
+ {
+ "threshold": 7000,
+ "id": "hot_start",
+ "giftable": true,
+ "name": "Hot start",
+ "max": 3,
+ "help": "Clear the level quickly."
+ },
+ {
+ "threshold": 9000,
+ "id": "sapper",
+ "giftable": true,
+ "name": "Bricks become bombs",
+ "max": 1,
+ "help": "Broken blocks become bombs."
+ },
+ {
+ "threshold": 11000,
+ "id": "bigger_explosions",
+ "name": "Bigger explosions",
+ "max": 1,
+ "help": "Larger bomb area of effect."
+ },
+ {
+ "threshold": 13000,
+ "id": "extra_levels",
+ "name": "+1 level",
+ "max": 3,
+ "help": "Play one more level before winning."
+ },
+ {
+ "threshold": 15000,
+ "id": "pierce_color",
+ "name": "Color pierce",
+ "color_blind_exclude": true,
+ "max": 1,
+ "help": "Ball breaks same color bricks."
+ },
+ {
+ "threshold": 18000,
+ "id": "soft_reset",
+ "name": "Soft reset",
+ "max": 2,
+ "help": "Combo grows slower but resets less"
+ },
+ {
+ "threshold": 21000,
+ "id": "ball_repulse_ball",
+ "name": "Balls repulse balls",
+ requires: 'multiball',
+ "max": 3,
+ "help": "Only has an effect with 2+ balls."
+ },
+ {
+ "threshold": 25000,
+ "id": "ball_attract_ball",
+ requires: 'multiball',
+ "name": "Balls attract balls",
+ "max": 3,
+ "help": "Only has an effect with 2+ balls."
+ },
+ {
+ "threshold": 30000,
+ "id": "puck_repulse_ball",
+ "name": "Puck repulse balls",
+ "max": 3,
+ "help": "Prevents the puck from touching the balls.",
+ },
+]
+
+
+let totalScoreAtRunStart = getTotalScore()
+
+function getPossibleUpgrades() {
+ return upgrades
+ .filter(u => !(isSettingOn('color_blind') && u.color_blind_exclude))
+ .filter(u => totalScoreAtRunStart >= u.threshold)
+ .filter(u => !u.requires || perks[u.requires])
+}
+
+
+function shuffleLevels(nameToAvoid = null) {
+
+ runLevels = allLevels
+ .filter(l => nextRunOverrides.level ? l.name === nextRunOverrides.level : true)
+ .filter((l, li) => totalScoreAtRunStart >= l.threshold)
+ .filter(l => l.name !== nameToAvoid || allLevels.length === 1)
+ .sort(() => Math.random() - 0.5)
+ .slice(0, 7 + 3)
+ .sort((a, b) => a.sortKey - b.sortKey);
+
+ nextRunOverrides.level = null
+}
+
+function getUpgraderUnlockPoints() {
+ let list = []
+
+ upgrades
+ .filter(u => !(isSettingOn('color_blind') && u.color_blind_exclude))
+ .forEach(u => {
+ if (u.threshold) {
+ list.push({
+ threshold: u.threshold,
+ title: u.name + ' (Perk)'
+ })
+ }
+ })
+
+ allLevels.forEach((l, li) => {
+ list.push({
+ threshold: l.threshold,
+ title: l.name + ' (Level)',
+ })
+ })
+
+ return list.filter(o => o.threshold).sort((a, b) => a.threshold - b.threshold)
+}
+
+
+let lastOffered = {}
+
+function pickRandomUpgrades(count) {
+
+ let list = getPossibleUpgrades()
+ .map(u => ({...u, score: Math.random() + (lastOffered[u.id] || 0)}))
+ .sort((a, b) => a.score - b.score)
+ .filter(u => perks[u.id] < u.max)
+ .slice(0, count)
+ .sort((a, b) => a.id > b.id ? 1 : -1)
+
+ list.forEach(u => {
+ incrementRunStatistics('offered_upgrade.' + u.id, 1)
+ lastOffered[u.id] = Math.round(Date.now() / 1000)
+ })
+
+ return list.map(u => ({
+ text: u.name + (perks[u.id]?' lvl '+(perks[u.id]+1):''),
+ icon: u.icon,
+ value: () => {
+ perks[u.id]++;
+ incrementRunStatistics('picked_upgrade.' + u.id, 1)
+ scoreStory.push("Picked upgrade : " + u.name);
+ },
+ help: u.help,
+ // max: u.max,
+ // checked: perks[u.id]
+ }))
+
+
+}
+
+let nextRunOverrides = {level: null, perks: null}
+let hadOverrides = false
+
+function restart() {
+ console.log("restart")
+ hadOverrides = !!(nextRunOverrides.level || nextRunOverrides.perks)
+ // When restarting, we want to avoid restarting with the same level we're on, so we exclude from the next
+ // run's level list
+ totalScoreAtRunStart = getTotalScore()
+ shuffleLevels(levelTime || score ? currentLevelInfo().name : null);
+ resetRunStatistics()
+ score = 0;
+ scoreStory = [];
+ if (hadOverrides) {
+ scoreStory.push(`This is a test run, started from the unlocks menu. It stops after one level and is not recorded in the stats. `)
+ }
+ const randomGift = reset_perks();
+
+ incrementRunStatistics('starting_upgrade.' + randomGift, 1)
+
+ setLevel(0);
+ scoreStory.push(`You started playing with the upgrade "${upgrades.find(u => u.id === randomGift)?.name}" on the level "${runLevels[0].name}". `,);
+}
+
+function setMousePos(x) {
+
+ needsRender = true;
+ puck = x;
+
+ // We have borders visible, enforce them
+ if (puck < offsetXRoundedDown + puckWidth / 2) {
+ puck = offsetXRoundedDown + puckWidth / 2;
+ }
+ if (puck > offsetXRoundedDown + gameZoneWidthRoundedUp - puckWidth / 2) {
+ puck = offsetXRoundedDown + gameZoneWidthRoundedUp - puckWidth / 2;
+ }
+ if (!running && !levelTime) {
+ putBallsAtPuck();
+ }
+}
+
+canvas.addEventListener("mouseup", (e) => {
+ if (e.button !== 0) return;
+ if (running) {
+ pause()
+ } else {
+ play()
+ }
+});
+
+canvas.addEventListener("mousemove", (e) => {
+ setMousePos(e.x);
+});
+
+canvas.addEventListener("touchstart", (e) => {
+ e.preventDefault();
+ if (!e.touches?.length) return;
+ setMousePos(e.touches[0].pageX);
+ play()
+});
+canvas.addEventListener("touchend", (e) => {
+ e.preventDefault();
+ pause()
+});
+canvas.addEventListener("touchcancel", (e) => {
+ e.preventDefault();
+ pause()
+ needsRender = true
+});
+canvas.addEventListener("touchmove", (e) => {
+ if (!e.touches?.length) return;
+ setMousePos(e.touches[0].pageX);
+});
+
+let lastTick = performance.now();
+
+function brickIndex(x, y) {
+ return getRowColIndex(Math.floor(y / brickWidth), Math.floor((x - offsetX) / brickWidth),);
+}
+
+function hasBrick(index) {
+ if (bricks[index]) return index;
+}
+
+function hitsSomething(x, y, radius) {
+ return (hasBrick(brickIndex(x - radius, y - radius)) ?? hasBrick(brickIndex(x + radius, y - radius)) ?? hasBrick(brickIndex(x + radius, y + radius)) ?? hasBrick(brickIndex(x - radius, y + radius)));
+}
+
+function shouldPierceByColor(ballOrCoin, vhit, hhit, chit) {
+ if (!perks.pierce_color) return false
+ // if (ballOrCoin.color === 'white') return true
+ if (typeof vhit !== 'undefined' && bricks[vhit] !== ballOrCoin.color) {
+ return false
+ }
+ if (typeof hhit !== 'undefined' && bricks[hhit] !== ballOrCoin.color) {
+ return false
+ }
+ if (typeof chit !== 'undefined' && bricks[chit] !== ballOrCoin.color) {
+ return false
+ }
+ return true
+}
+
+function brickHitCheck(ballOrCoin, radius, isBall) {
+ // Make ball/coin bonce, and return bricks that were hit
+ const {x, y, previousx, previousy} = ballOrCoin;
+
+ const vhit = hitsSomething(previousx, y, radius);
+ const hhit = hitsSomething(x, previousy, radius);
+ const chit = (typeof vhit == "undefined" && typeof hhit == "undefined" && hitsSomething(x, y, radius)) || undefined;
+
+
+ let pierce = isBall && ballOrCoin.piercedSinceBounce < perks.pierce * 3;
+ if (pierce && (typeof vhit !== "undefined" || typeof hhit !== "undefined" || typeof chit !== "undefined")) {
+ ballOrCoin.piercedSinceBounce++
+ }
+ if (isBall && shouldPierceByColor(ballOrCoin, vhit, hhit, chit)) {
+ pierce = true
+ }
+
+
+ if (typeof vhit !== "undefined" || typeof chit !== "undefined") {
+ if (!pierce) {
+ ballOrCoin.y = ballOrCoin.previousy;
+ ballOrCoin.vy *= -1;
+ }
+
+ if (!isBall) {
+ // Roll on corners
+ const leftHit = bricks[brickIndex(x - radius, y + radius)];
+ const rightHit = bricks[brickIndex(x + radius, y + radius)];
+
+ if (leftHit && !rightHit) {
+ ballOrCoin.vx += 1;
+ }
+ if (!leftHit && rightHit) {
+ ballOrCoin.vx -= 1;
+ }
+ }
+ }
+ if (typeof hhit !== "undefined" || typeof chit !== "undefined") {
+ if (!pierce) {
+ ballOrCoin.x = ballOrCoin.previousx;
+ ballOrCoin.vx *= -1;
+ }
+ }
+
+ return vhit ?? hhit ?? chit;
+}
+
+function bordersHitCheck(coin, radius, delta) {
+ if (coin.destroyed) return;
+ coin.previousx = coin.x;
+ coin.previousy = coin.y;
+ coin.x += coin.vx * delta;
+ coin.y += coin.vy * delta;
+ coin.sx ||= 0;
+ coin.sy ||= 0;
+ coin.sx += coin.previousx - coin.x;
+ coin.sy += coin.previousy - coin.y;
+ coin.sx *= 0.9;
+ coin.sy *= 0.9;
+
+ let vhit = 0, hhit = 0;
+
+
+ if (coin.x < offsetXRoundedDown + radius) {
+ coin.x = offsetXRoundedDown + radius;
+ coin.vx *= -1;
+ hhit = 1;
+ }
+ if (coin.y < radius) {
+ coin.y = radius;
+ coin.vy *= -1;
+ vhit = 1;
+ }
+ if (coin.x > canvas.width - offsetXRoundedDown - radius) {
+ coin.x = canvas.width - offsetXRoundedDown - radius;
+ coin.vx *= -1;
+ hhit = 1;
+ }
+
+ return hhit + vhit * 2;
+}
+
+let lastTickDown = 0;
+
+function tick() {
+
+ recomputeTargetBaseSpeed();
+ const currentTick = performance.now();
+
+ puckWidth = (gameZoneWidth / 12) * (3 - perks.smaller_puck + perks.bigger_puck);
+
+ if (running) {
+
+ levelTime += currentTick - lastTick;
+ // How many time to compute
+ let delta = Math.min(4, (currentTick - lastTick) / (1000 / 60));
+ delta *= running ? 1 : 0
+
+
+ coins = coins.filter((coin) => !coin.destroyed);
+ balls = balls.filter((ball) => !ball.destroyed);
+
+ const remainingBricks = bricks.filter((b) => b && b !== "black").length;
+
+ if (levelTime > lastTickDown + 1000 && perks.hot_start) {
+ lastTickDown = levelTime;
+ decreaseCombo(perks.hot_start, puck, gameZoneHeight - 2 * puckHeight);
+ }
+
+ if (remainingBricks < perks.skip_last) {
+ bricks.forEach((type, index) => {
+ if (type) {
+ explodeBrick(index, balls[0], true);
+ }
+ });
+ }
+ if (!remainingBricks && !coins.length) {
+ incrementRunStatistics('level_time', levelTime)
+
+ if (currentLevel + 1 < max_levels()) {
+ setLevel(currentLevel + 1);
+ } else {
+ gameOver("Run finished with " + score + " points", "You cleared all levels for this run.");
+ }
+ } else if (running || levelTime) {
+ let playedCoinBounce = false;
+ const coinRadius = Math.round(coinSize / 2);
+
+
+ coins.forEach((coin) => {
+ if (coin.destroyed) return;
+ if (perks.coin_magnet) {
+ coin.vx += ((delta * (puck - coin.x)) / (100 + Math.pow(coin.y - gameZoneHeight, 2) + Math.pow(coin.x - puck, 2))) * perks.coin_magnet * 100;
+ }
+
+ const ratio = 1 - (perks.viscosity * 0.03 + 0.005) * delta;
+
+ coin.vy *= ratio;
+ coin.vx *= ratio;
+
+ // Gravity
+ coin.vy += delta * coin.weight * 0.8;
+
+ const speed = Math.abs(coin.sx) + Math.abs(coin.sx);
+ const hitBorder = bordersHitCheck(coin, coinRadius, delta);
+
+ if (coin.y > gameZoneHeight - coinRadius - puckHeight && coin.y < gameZoneHeight + puckHeight + coin.vy && Math.abs(coin.x - puck) < coinRadius + puckWidth / 2 + // a bit of margin to be nice
+ puckHeight) {
+ addToScore(coin);
+
+ } else if (coin.y > canvas.height + coinRadius) {
+ coin.destroyed = true;
+ if (perks.catch_all_coins) {
+ decreaseCombo(coin.points * perks.catch_all_coins, coin.x, canvas.height - coinRadius);
+ }
+ }
+
+ const hitBrick = brickHitCheck(coin, coinRadius, false);
+
+ if (perks.metamorphosis && typeof hitBrick !== "undefined") {
+ if (bricks[hitBrick] && coin.color !== bricks[hitBrick] && bricks[hitBrick] !== "black" && !coin.coloredABrick) {
+ bricks[hitBrick] = coin.color;
+ coin.coloredABrick = true
+ }
+ }
+ if (typeof hitBrick !== "undefined" || hitBorder) {
+ coin.vx *= 0.8;
+ coin.vy *= 0.8;
+
+ if (speed > 20 && !playedCoinBounce) {
+ playedCoinBounce = true;
+ sounds.coinBounce(coin.x, 0.2);
+ }
+
+ if (Math.abs(coin.vy) < 3) {
+ coin.vy = 0;
+ }
+ }
+ });
+
+ balls.forEach((ball) => ballTick(ball, delta));
+
+ flashes.forEach((flash) => {
+ if (flash.type === "particle") {
+ flash.x += flash.vx * delta;
+ flash.y += flash.vy * delta;
+ if (!flash.ethereal) {
+ flash.vy += 0.5;
+ if (hasBrick(brickIndex(flash.x, flash.y))) {
+ flash.destroyed = true;
+ }
+ }
+ }
+ });
+ }
+ }
+
+ render();
+
+ requestAnimationFrame(tick);
+ lastTick = currentTick;
+}
+
+function isTelekinesisActive(ball) {
+ return perks.telekinesis && !ball.hitSinceBounce && ball.vy < 0;
+}
+
+function ballTick(ball, delta) {
+ ball.previousvx = ball.vx;
+ ball.previousvy = ball.vy;
+
+ if (isTelekinesisActive(ball)) {
+ ball.vx += ((puck - ball.x) / 1000) * delta * perks.telekinesis;
+ }
+
+ const speedLimitDampener = 1 + perks.telekinesis + perks.ball_repulse_ball + perks.puck_repulse_ball + perks.ball_attract_ball
+ if (ball.vx * ball.vx + ball.vy * ball.vy < baseSpeed * baseSpeed * 2) {
+ ball.vx *= (1 + .02 / speedLimitDampener);
+ ball.vy *= (1 + .02 / speedLimitDampener);
+ } else {
+ ball.vx *= (1 - .02 / speedLimitDampener);
+ ;
+ if (Math.abs(ball.vy) > 0.5 * baseSpeed) {
+ ball.vy *= (1 - .02 / speedLimitDampener);
+ ;
+ }
+ }
+
+ if (perks.ball_repulse_ball) {
+ for (b2 of balls) {
+ // avoid computing this twice, and repulsing itself
+ if (b2.x >= ball.x) continue
+ repulse(ball, b2, perks.ball_repulse_ball, true)
+ }
+ }
+ if (perks.ball_attract_ball) {
+ for (b2 of balls) {
+ // avoid computing this twice, and repulsing itself
+ if (b2.x >= ball.x) continue
+ attract(ball, b2, perks.ball_attract_ball)
+ }
+ }
+ if (perks.puck_repulse_ball) {
+ repulse(ball, {
+ x: puck,
+ y: gameZoneHeight,
+ color: currentLevelInfo().black_puck ? '#000' : '#FFF',
+ }, perks.puck_repulse_ball, false)
+ }
+
+
+ const borderHitCode = bordersHitCheck(ball, ballSize / 2, delta);
+ if (borderHitCode) {
+ if (perks.sides_are_lava && borderHitCode % 2) {
+ resetCombo(ball.x, ball.y);
+ }
+ if (perks.top_is_lava && borderHitCode >= 2) {
+ resetCombo(ball.x, ball.y + ballSize);
+ }
+ sounds.wallBeep(ball.x);
+ ball.bouncesList?.push({x: ball.previousx, y: ball.previousy})
+ }
+
+ // Puck collision
+ const ylimit = gameZoneHeight - puckHeight - ballSize / 2;
+ if (ball.y > ylimit && Math.abs(ball.x - puck) < ballSize / 2 + puckWidth / 2 && ball.vy > 0) {
+ const speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
+ const angle = Math.atan2(-puckWidth / 2, ball.x - puck);
+ ball.vx = speed * Math.cos(angle);
+ ball.vy = speed * Math.sin(angle);
+
+ sounds.wallBeep(ball.x);
+ if (perks.streak_shots) {
+ resetCombo(ball.x, ball.y);
+ }
+ if (!ball.hitSinceBounce) {
+ incrementRunStatistics('miss')
+ levelMisses++;
+ flashes.push({
+ type: "text",
+ text: 'miss',
+ time: levelTime,
+ color: ball.color,
+ x: ball.x,
+ y: ball.y - ballSize,
+ duration: 450,
+ size: puckHeight,
+ })
+ if (ball.bouncesList?.length) {
+ ball.bouncesList.push({
+ x: ball.previousx,
+ y: ball.previousy
+ })
+ for (si = 0; si < ball.bouncesList.length - 1; si++) {
+ // segement
+ const start = ball.bouncesList[si]
+ const end = ball.bouncesList[si + 1]
+ const distance = distanceBetween(start, end)
+
+ const parts = distance / 30
+ for (var i = 0; i < parts; i++) {
+ flashes.push({
+ type: "particle",
+ duration: 200,
+ ethereal: true,
+ time: levelTime,
+ size: coinSize / 2,
+ color: ball.color,
+ x: start.x + (i / (parts - 1)) * (end.x - start.x),
+ y: start.y + (i / (parts - 1)) * (end.y - start.y),
+ vx: (Math.random() - 0.5) * baseSpeed,
+ vy: (Math.random() - 0.5) * baseSpeed,
+ });
+ }
+ }
+ }
+
+ }
+ incrementRunStatistics('puck_bounces')
+ ball.hitSinceBounce = 0;
+ ball.piercedSinceBounce = 0;
+ ball.bouncesList = [{
+ x: ball.previousx,
+ y: ball.previousy
+ }]
+ }
+
+ if (ball.y > gameZoneHeight + ballSize / 2 && running) {
+ ball.destroyed = true;
+ if (!balls.find((b) => !b.destroyed)) {
+ if (perks.extra_life) {
+ perks.extra_life--;
+ resetBalls();
+ sounds.revive();
+ pause()
+ coins = [];
+ flashes.push({
+ type: "ball",
+ duration: 500,
+ time: levelTime,
+ size: brickWidth * 2,
+ color: "white",
+ x: ball.x,
+ y: ball.y,
+ });
+ } else {
+ gameOver("Game Over", "You dropped the ball after catching " + score + " coins. ");
+ }
+ }
+ }
+ const hitBrick = brickHitCheck(ball, ballSize / 2, true);
+ if (typeof hitBrick !== "undefined") {
+ const wasABomb = bricks[hitBrick] === "black";
+ explodeBrick(hitBrick, ball, false);
+
+ if (perks.sapper && !wasABomb) {
+ bricks[hitBrick] = "black";
+ }
+ }
+
+ if (!isSettingOn("basic")) {
+ ball.sparks += (delta * (combo - 1)) / 30;
+ if (ball.sparks > 1) {
+ flashes.push({
+ type: "particle",
+ duration: 100 * ball.sparks,
+ time: levelTime,
+ size: coinSize / 2,
+ color: ball.color,
+ x: ball.x,
+ y: ball.y,
+ vx: (Math.random() - 0.5) * baseSpeed,
+ vy: (Math.random() - 0.5) * baseSpeed,
+ });
+ ball.sparks = 0;
+ }
+ }
+}
+
+
+let runStatistics = {};
+
+function resetRunStatistics() {
+ runStatistics = {
+ started: Date.now(),
+ ended: null,
+ hadOverrides,
+ width: window.innerWidth,
+ height: window.innerHeight,
+ easy: isSettingOn('easy'),
+ color_blind: isSettingOn('color_blind'),
+ }
+}
+
+
+function incrementRunStatistics(key, amount = 1) {
+ runStatistics[key + '_total'] = (runStatistics[key + '_total'] || 0) + amount
+ runStatistics[key + '_lvl_' + currentLevel] = (runStatistics[key + '_lvl_' + currentLevel] || 0) + amount
+}
+
+function getTotalScore() {
+ try {
+ return JSON.parse(localStorage.getItem('breakout_71_total_score') || '0')
+ } catch (e) {
+ return 0
+ }
+}
+
+function addToTotalScore(points) {
+ if (hadOverrides) return
+ try {
+ localStorage.setItem('breakout_71_total_score', JSON.stringify(getTotalScore() + points))
+ } catch (e) {
+ }
+}
+
+function gameOver(title, intro) {
+ if (!running) return;
+ pause()
+
+ runStatistics.ended = Date.now()
+
+ const {stats} = getLevelStats();
+
+ scoreStory.push(`During level ${currentLevel + 1} ${stats}`);
+ if (balls.find((b) => !b.destroyed)) {
+ scoreStory.push(`You cleared the last level and won. `);
+ } else {
+ scoreStory.push(`You dropped the ball and finished your run early. `);
+ }
+
+ try {
+ // Stores only last 100 runs
+ const runsHistory = JSON.parse(localStorage.getItem('breakout_71_history') || '[]').slice(0, 99).concat([runStatistics])
+
+ // Generate some histogram
+
+ localStorage.setItem('breakout_71_history', '' + JSON.stringify(runsHistory, null, 2) + ' ')
+ } catch {
+ }
+
+ let animationDelay = -300
+ const getDelay = () => {
+ animationDelay += 800
+ return 'animation-delay:' + animationDelay + 'ms;'
+ }
+ // unlocks
+ let unlocksInfo = ''
+ const endTs = getTotalScore()
+ const startTs = endTs - score
+ const list = getUpgraderUnlockPoints()
+ list.filter(u => u.threshold > startTs && u.threshold < endTs).forEach(u => {
+ unlocksInfo += `
+
+ ${u.title}
+
+
+`
+ })
+
+ const previousUnlockAt = list.findLast(u => u.threshold <= endTs)?.threshold || 0
+ const nextUnlock = list.find(u => u.threshold > endTs)
+
+ if (nextUnlock) {
+ const total = nextUnlock?.threshold - previousUnlockAt
+ const done = endTs - previousUnlockAt
+ intro += `Score ${nextUnlock.threshold - endTs} more points to reach the next unlock.`
+
+ const scaleX = (done / total).toFixed(2)
+ unlocksInfo += `
+
+ ${nextUnlock.title}
+
+
+
+`
+ list.slice(list.indexOf(nextUnlock) + 1).slice(0, 3).forEach(u => {
+ unlocksInfo += `
+
+ ${u.title}
+
+`
+ })
+ }
+
+ // Avoid the sad sound right as we restart a new games
+ combo = 1
+ asyncAlert({
+ allowClose: true, title, text: `
+ ${intro}
+ ${unlocksInfo}
+ `, textAfterButtons: `
+
+ ${scoreStory.map((t) => "" + t + "
").join("")}
+ `
+ }).then(() => restart());
+}
+
+function explodeBrick(index, ball, isExplosion) {
+ const color = bricks[index];
+ if (color === 'black') {
+ delete bricks[index];
+ const x = brickCenterX(index), y = brickCenterY(index);
+
+ incrementRunStatistics('explosion', 1)
+ sounds.explode(ball.x);
+ const {col, row} = getRowCol(index);
+ const size = 1 + perks.bigger_explosions;
+ // Break bricks around
+ for (let dx = -size; dx <= size; dx++) {
+ for (let dy = -size; dy <= size; dy++) {
+ const i = getRowColIndex(row + dy, col + dx);
+ if (bricks[i] && i !== -1) {
+ explodeBrick(i, ball, true)
+ }
+ }
+ }
+ // Blow nearby coins
+ coins.forEach((c) => {
+ const dx = c.x - x;
+ const dy = c.y - y;
+ const d2 = Math.max(brickWidth, Math.abs(dx) + Math.abs(dy));
+ c.vx += (dx / d2) * 10 * size / c.weight;
+ c.vy += (dy / d2) * 10 * size / c.weight;
+ });
+ lastexplosion = Date.now();
+
+ flashes.push({
+ type: "ball", duration: 150, time: levelTime, size: brickWidth * 2, color: "white", x, y,
+ });
+ spawnExplosion(7 * (1 + perks.bigger_explosions), x, y, 'white', 150, coinSize,);
+ ball.hitSinceBounce++;
+ } else if (color) {
+ // Flashing is take care of by the tick loop
+ const x = brickCenterX(index), y = brickCenterY(index);
+
+ bricks[index] = "";
+
+ levelSpawnedCoins += combo;
+
+ incrementRunStatistics('spawned_coins', combo)
+
+ coins = coins.filter((c) => !c.destroyed);
+ for (let i = 0; i < combo; i++) {
+ // Avoids saturating the canvas with coins
+ if (coins.length > MAX_COINS * (isSettingOn("basic") ? 0.5 : 1)) {
+ // Just pick a random one
+ coins[Math.floor(Math.random() * coins.length)].points++;
+ continue;
+ }
+
+ const coord = {
+ x: x + (Math.random() - 0.5) * (brickWidth - coinSize),
+ y: y + (Math.random() - 0.5) * (brickWidth - coinSize),
+ };
+
+ coins.push({
+ points: 1,
+ color, ...coord,
+ previousx: coord.x,
+ previousy: coord.y,
+
+ // Use previous speed because the ball has already bounced
+ vx: ball.previousvx * (0.5 + Math.random()),
+ vy: ball.previousvy * (0.5 + Math.random()),
+ sx: 0,
+ sy: 0,
+ weight: 0.8 + Math.random() * 0.2
+ });
+ }
+
+
+ combo += Math.max(0,perks.streak_shots + perks.catch_all_coins + perks.sides_are_lava + perks.top_is_lava + perks.picky_eater
+ - Math.round(Math.random()*perks.soft_reset));
+
+ if (!isExplosion) {
+ // color change
+ if ((perks.picky_eater || perks.pierce_color) && color !== ball.color) {
+ // reset streak
+ if (perks.picky_eater) resetCombo(ball.x, ball.y);
+ ball.color = color;
+ } else {
+ sounds.comboIncreaseMaybe(ball.x, 1);
+ }
+ }
+ ball.hitSinceBounce++;
+
+ flashes.push({
+ type: "ball", duration: 40, time: levelTime, size: brickWidth, color: color, x, y,
+ });
+ spawnExplosion(5 + combo, x, y,color, 100, coinSize / 2);
+ }
+}
+
+function max_levels() {
+ if (hadOverrides) return 1
+ return 7 + perks.extra_levels;
+}
+
+function render() {
+ if (running) needsRender = true
+ if (!needsRender) {
+ return
+ }
+ needsRender = false;
+
+ const level = currentLevelInfo();
+ const {width, height} = canvas;
+ if (!width || !height) return;
+
+ let scoreInfo = "";
+ for (let i = 0; i < perks.extra_life; i++) {
+ scoreInfo += "🖤 ";
+ }
+
+ scoreInfo += score.toString();
+ scoreDisplay.innerText = scoreInfo;
+
+
+ if (!isSettingOn("basic") && !level.color && level.svg && !level.black_puck) {
+
+ // Without this the light trails everything
+ ctx.globalCompositeOperation = "source-over";
+ ctx.globalAlpha = .4
+ ctx.fillStyle = "#000";
+ ctx.fillRect(0, 0, width, height);
+
+
+ ctx.globalCompositeOperation = "screen";
+ ctx.globalAlpha = 0.6;
+ coins.forEach((coin) => {
+ if (!coin.destroyed) drawFuzzyBall(ctx, coin.color, coinSize * 2, coin.x, coin.y);
+ });
+ balls.forEach((ball) => {
+ drawFuzzyBall(ctx, ball.color, ballSize * 2, ball.x, ball.y);
+ });
+ ctx.globalAlpha = 0.5;
+ bricks.forEach((color, index) => {
+ if (!color) return;
+ const x = brickCenterX(index), y = brickCenterY(index);
+ drawFuzzyBall(ctx, color == 'black' ? '#666' : color, brickWidth, x, y);
+ });
+ ctx.globalAlpha = 1;
+ flashes.forEach((flash) => {
+ const {x, y, time, color, size, type, duration} = flash;
+ const elapsed = levelTime - time;
+ ctx.globalAlpha = Math.min(1, 2 - (elapsed / duration) * 2);
+ if (type === "ball") {
+ drawFuzzyBall(ctx, color, size, x, y);
+ }
+ if (type === "particle") {
+ drawFuzzyBall(ctx, color, size * 3, x, y);
+ }
+
+ });
+ // Decides how brights the bg black parts can get
+ ctx.globalAlpha = .2;
+ ctx.globalCompositeOperation = "multiply";
+ ctx.fillStyle = "black";
+ ctx.fillRect(0, 0, width, height);
+ // Decides how dark the background black parts are when lit (1=black)
+ ctx.globalAlpha = .8;
+ ctx.globalCompositeOperation = "multiply";
+ if (level.svg) {
+ if (backgroundCanvas.title !== level.name && background.complete) {
+ backgroundCanvas.title = level.name
+ backgroundCanvas.width = canvas.width
+ backgroundCanvas.height = canvas.height
+ const bgctx = backgroundCanvas.getContext("2d")
+ bgctx.fillStyle = level.color
+ bgctx.fillRect(0, 0, canvas.width, canvas.height)
+ bgctx.fillStyle = ctx.createPattern(background, "repeat");
+ bgctx.fillRect(0, 0, width, height);
+ console.log("redrew context")
+ }
+ if (background.complete) {
+ ctx.drawImage(backgroundCanvas, 0, 0)
+ } else {
+ // Background not loaded yes
+ ctx.fillStyle = "#000";
+ ctx.fillRect(0, 0, width, height);
+ }
+ }
+ } else {
+
+ ctx.globalAlpha = 1
+ ctx.globalCompositeOperation = "source-over";
+ ctx.fillStyle = level.color || "#000";
+ ctx.fillRect(0, 0, width, height);
+
+ flashes.forEach((flash) => {
+ const {x, y, time, color, size, type, duration} = flash;
+ const elapsed = levelTime - time;
+ ctx.globalAlpha = Math.min(1, 2 - (elapsed / duration) * 2);
+ if (type === "particle") {
+ drawBall(ctx, color, size, x, y);
+ }
+ });
+ }
+
+ if (combo > baseCombo()) {
+ // The red should still be visible on a white bg
+ ctx.globalCompositeOperation = !level.color && level.svg ? "screen" : 'source-over';
+ ctx.globalAlpha = (2 + combo - baseCombo()) / 50;
+ const baseParticle = !isSettingOn('basic') && (combo - baseCombo()) * Math.random() > 5 && running && {
+ type: "particle",
+ duration: 100 * (Math.random() + 1),
+ time: levelTime,
+ size: coinSize / 2,
+ color: 'red',
+ ethereal: true,
+ }
+
+ if (perks.top_is_lava) {
+ drawRedGradientSquare(ctx, offsetXRoundedDown, 0, gameZoneWidthRoundedUp, ballSize, 0, 0, 0, ballSize);
+ baseParticle && flashes.push({
+ ...baseParticle,
+ x: offsetXRoundedDown + Math.random() * gameZoneWidthRoundedUp,
+ y: 0,
+ vx: (Math.random() - 0.5) * 10,
+ vy: 5,
+ })
+ }
+ if (perks.sides_are_lava) {
+ drawRedGradientSquare(ctx, offsetXRoundedDown, 0, ballSize, gameZoneHeight, 0, 0, ballSize, 0,);
+ drawRedGradientSquare(ctx, offsetXRoundedDown + gameZoneWidthRoundedUp - ballSize, 0, ballSize, gameZoneHeight, ballSize, 0, 0, 0,);
+ const fromLeft = Math.random() > 0.5
+ baseParticle && flashes.push({
+ ...baseParticle,
+ x: offsetXRoundedDown + (fromLeft ? 0 : gameZoneWidthRoundedUp),
+ y: Math.random() * gameZoneHeight,
+ vx: fromLeft ? 5 : -5,
+ vy: (Math.random() - 0.5) * 10,
+ })
+ }
+ if (perks.catch_all_coins) {
+ drawRedGradientSquare(ctx, offsetXRoundedDown, gameZoneHeight - ballSize, gameZoneWidthRoundedUp, ballSize, 0, ballSize, 0, 0,);
+ let x = puck
+ do {
+ x = offsetXRoundedDown + gameZoneWidthRoundedUp * Math.random()
+ } while (Math.abs(x - puck) < puckWidth / 2)
+ baseParticle && flashes.push({
+ ...baseParticle,
+ x,
+ y: gameZoneHeight,
+ vx: (Math.random() - 0.5) * 10,
+ vy: -5,
+ })
+ }
+ if (perks.streak_shots) {
+ drawRedGradientSquare(ctx, puck - puckWidth / 2, gameZoneHeight - puckHeight - ballSize, puckWidth, ballSize, 0, ballSize, 0, 0,);
+ const pos = (0.5 - Math.random())
+ baseParticle && flashes.push({
+ ...baseParticle,
+ duration: 100,
+ x: puck + puckWidth * pos,
+ y: gameZoneHeight - puckHeight,
+ vx: (pos) * 10,
+ vy: -5,
+ })
+ }
+ if (perks.picky_eater) {
+ let okColors = new Set(balls.map((b) => b.color));
+
+ bricks.forEach((type, index) => {
+ if (!type || type === "black" || okColors.has(type)) return;
+ const x = brickCenterX(index), y = brickCenterY(index);
+ drawFuzzyBall(ctx, "red", brickWidth, x, y);
+ //
+ // baseParticle && flashes.push({
+ // ...baseParticle,
+ // duration: 100,
+ // x,
+ // y,
+ // vx: (0.5 - Math.random()) * 10,
+ // vy: (0.5 - Math.random()) * 10,
+ // })
+ });
+ }
+ ctx.globalAlpha = 1;
+ }
+
+ ctx.globalAlpha = 1;
+ ctx.globalCompositeOperation = "source-over";
+ const lastExplosionDelay = Date.now() - lastexplosion + 5;
+ const shaked = lastExplosionDelay < 200;
+ if (shaked) {
+ const amplitude = (perks.bigger_explosions + 1) * 50 / lastExplosionDelay
+ ctx.translate(Math.sin(Date.now()) * amplitude, Math.sin(Date.now() + 36) * amplitude);
+ }
+
+ ctx.globalCompositeOperation = "source-over";
+ renderAllBricks(ctx);
+
+ ctx.globalCompositeOperation = "screen";
+ flashes = flashes.filter((f) => levelTime - f.time < f.duration && !f.destroyed,);
+
+ flashes.forEach((flash) => {
+ const {x, y, time, color, size, type, text, duration, points} = flash;
+ const elapsed = levelTime - time;
+ ctx.globalAlpha = Math.max(0, Math.min(1, 2 - (elapsed / duration) * 2));
+ if (type === "text") {
+ ctx.globalCompositeOperation = "source-over";
+ drawText(ctx, text, color, size, {x, y: y - elapsed / 10});
+ } else if (type === "particle") {
+ ctx.globalCompositeOperation = "screen";
+ drawBall(ctx, color, size, x, y);
+ drawFuzzyBall(ctx, color, size, x, y);
+ }
+ });
+
+ // Coins
+ ctx.globalAlpha = 1;
+ ctx.globalCompositeOperation = "source-over";
+ coins.forEach((coin) => {
+ if (!coin.destroyed) drawCoin(ctx, coin.color, coinSize, coin, level.color || 'black');
+ });
+
+
+ // Black shadow around balls
+ if (coins.length > 10 && !isSettingOn('basic')) {
+ ctx.globalAlpha = Math.min(0.8, (coins.length - 10) / 50);
+ balls.forEach((ball) => {
+ drawBall(ctx, level.color || "#000", ballSize * 6, ball.x, ball.y);
+ });
+ }
+
+
+ ctx.globalAlpha = 1
+ ctx.globalCompositeOperation = "source-over";
+ const puckColor = level.black_puck ? '#000' : '#FFF'
+ balls.forEach((ball) => {
+ drawBall(ctx, ball.color, ballSize, ball.x, ball.y);
+ // effect
+ if (isTelekinesisActive(ball)) {
+ ctx.strokeStyle = puckColor;
+ ctx.beginPath();
+ ctx.bezierCurveTo(puck, gameZoneHeight, puck, ball.y, ball.x, ball.y);
+ ctx.stroke();
+ }
+ });
+ // The puck
+
+ ctx.globalAlpha = 1
+ ctx.globalCompositeOperation = "source-over";
+ drawPuck(ctx, puckColor, puckWidth, puckHeight)
+
+ if (combo > 1) {
+
+ ctx.globalCompositeOperation = "source-over";
+ drawText(ctx, "x " + combo, !level.black_puck ? '#000' : '#FFF', puckHeight, {
+ x: puck, y: gameZoneHeight - puckHeight / 2,
+ });
+ }
+ // Borders
+ ctx.fillStyle = puckColor;
+ ctx.globalCompositeOperation = "source-over";
+ if (offsetXRoundedDown) {
+ ctx.fillRect(offsetX, 0, 1, height);
+ ctx.fillRect(width - offsetX - 1, 0, 1, height);
+ }
+ if (isSettingOn("mobile-mode")) {
+ ctx.fillRect(offsetXRoundedDown, gameZoneHeight, gameZoneWidthRoundedUp, 1);
+ if (!running) {
+ drawText(ctx, "Keep pressing here to play", puckColor, puckHeight, {
+ x: canvas.width / 2, y: gameZoneHeight + (canvas.height - gameZoneHeight) / 2,
+ });
+ }
+ }
+
+ if (shaked) {
+ ctx.resetTransform();
+ }
+}
+
+let cachedBricksRender = document.createElement("canvas");
+let cachedBricksRenderKey = null;
+
+function renderAllBricks(destinationCtx) {
+ ctx.globalAlpha = 1;
+
+ const level = currentLevelInfo();
+
+ const newKey = gameZoneWidth + "_" + bricks.join("_") + bombSVG.complete;
+ if (newKey !== cachedBricksRenderKey) {
+ cachedBricksRenderKey = newKey;
+
+ cachedBricksRender.width = gameZoneWidth;
+ cachedBricksRender.height = gameZoneWidth + 1;
+ const ctx = cachedBricksRender.getContext("2d");
+ ctx.clearRect(0, 0, gameZoneWidth, gameZoneWidth);
+ ctx.resetTransform();
+ ctx.translate(-offsetX, 0);
+ // Bricks
+ bricks.forEach((color, index) => {
+ const x = brickCenterX(index), y = brickCenterY(index);
+
+ if (!color) return;
+ drawBrick(ctx, color, x, y, level.squared || false);
+ if (color === 'black') {
+ ctx.globalCompositeOperation = "source-over";
+ drawIMG(ctx, bombSVG, brickWidth, x, y);
+ }
+ });
+ }
+
+ destinationCtx.drawImage(cachedBricksRender, offsetX, 0);
+}
+
+let cachedGraphics = {};
+
+function drawPuck(ctx, color, puckWidth, puckHeight) {
+
+ const key = "puck" + color + "_" + puckWidth + '_' + puckHeight;
+
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = puckWidth;
+ can.height = puckHeight * 2;
+ const canctx = can.getContext("2d");
+ canctx.fillStyle = color;
+
+
+ canctx.beginPath();
+ canctx.moveTo(0, puckHeight * 2)
+ canctx.lineTo(0, puckHeight * 1.25)
+ canctx.bezierCurveTo(0, puckHeight * .75, puckWidth, puckHeight * .75, puckWidth, puckHeight * 1.25)
+ canctx.lineTo(puckWidth, puckHeight * 2)
+ canctx.fill();
+ cachedGraphics[key] = can;
+ }
+
+ ctx.drawImage(cachedGraphics[key], Math.round(puck - puckWidth / 2), gameZoneHeight - puckHeight * 2,);
+
+
+}
+
+function drawBall(ctx, color, width, x, y) {
+ const key = "ball" + color + "_" + width;
+
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ const size = Math.round(width);
+ can.width = size;
+ can.height = size;
+
+ const canctx = can.getContext("2d");
+ canctx.beginPath();
+ canctx.arc(size / 2, size / 2, Math.round(size / 2), 0, 2 * Math.PI);
+ canctx.fillStyle = color;
+ canctx.fill();
+ cachedGraphics[key] = can;
+ }
+ ctx.drawImage(cachedGraphics[key], Math.round(x - width / 2), Math.round(y - width / 2),);
+}
+
+function drawCoin(ctx, color, width, ball, bg) {
+ const key = "coin with halo" + "_" + color + "_" + width + '_' + bg;
+
+ const size = width * 3;
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = size;
+ can.height = size;
+
+ const canctx = can.getContext("2d");
+
+ // coin
+ canctx.beginPath();
+ canctx.arc(size / 2, size / 2, width / 2, 0, 2 * Math.PI);
+ canctx.fillStyle = color;
+ canctx.fill();
+
+ canctx.strokeStyle = bg;
+ canctx.stroke();
+
+ cachedGraphics[key] = can;
+ }
+ ctx.drawImage(cachedGraphics[key], Math.round(ball.x - size / 2), Math.round(ball.y - size / 2),);
+}
+
+function drawFuzzyBall(ctx, color, width, x, y) {
+ const key = "fuzzy-circle" + color + "_" + width;
+
+ const size = Math.round(width * 3);
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = size;
+ can.height = size;
+
+ const canctx = can.getContext("2d");
+ const gradient = canctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2,);
+ gradient.addColorStop(0, color);
+ gradient.addColorStop(1, "transparent");
+ canctx.fillStyle = gradient;
+ canctx.fillRect(0, 0, size, size);
+ cachedGraphics[key] = can;
+ }
+ ctx.drawImage(cachedGraphics[key], Math.round(x - size / 2), Math.round(y - size / 2),);
+}
+
+function drawBrick(ctx, color, x, y, squared) {
+ const tlx = Math.ceil(x - brickWidth / 2);
+ const tly = Math.ceil(y - brickWidth / 2);
+ const brx = Math.ceil(x + brickWidth / 2) - 1;
+ const bry = Math.ceil(y + brickWidth / 2) - 1;
+
+ const width = brx - tlx, height = bry - tly;
+ const key = "brick" + color + "_" + width + "_" + height + '_' + squared
+ // "_" +
+ // isSettingOn("rounded-bricks");
+
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = width;
+ can.height = height;
+ const canctx = can.getContext("2d");
+
+
+ if (squared) {
+
+ canctx.fillStyle = color;
+ canctx.fillRect(0, 0, width, height);
+ } else {
+
+ const bord = Math.floor(brickWidth / 6);
+ canctx.strokeStyle = color;
+ canctx.lineJoin = "round";
+ canctx.lineWidth = bord * 1.5;
+ canctx.strokeRect(bord, bord, width - bord * 2, height - bord * 2);
+
+ canctx.fillStyle = color;
+ canctx.fillRect(bord, bord, width - bord * 2, height - bord * 2);
+ }
+
+ cachedGraphics[key] = can;
+ }
+ ctx.drawImage(cachedGraphics[key], tlx, tly, width, height);
+ // It's not easy to have a 1px gap between bricks without antialiasing
+}
+
+function drawRedGradientSquare(ctx, x, y, width, height, redX, redY, blackX, blackY) {
+ const key = "gradient" + width + "_" + height + "_" + redX + "_" + redY + "_" + blackX + "_" + blackY;
+
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = width;
+ can.height = height;
+ const canctx = can.getContext("2d");
+
+ const gradient = canctx.createLinearGradient(redX, redY, blackX, blackY);
+ gradient.addColorStop(0, "rgba(255,0,0,1)");
+ gradient.addColorStop(1, "rgba(255,0,0,0)");
+ canctx.fillStyle = gradient;
+ canctx.fillRect(0, 0, width, height);
+ cachedGraphics[key] = can;
+ }
+
+ ctx.drawImage(cachedGraphics[key], x, y, width, height);
+}
+
+
+function drawIMG(ctx, img, size, x, y) {
+ const key = "svg" + img + "_" + size + '_' + img.complete;
+
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = size;
+ can.height = size;
+
+ const canctx = can.getContext("2d");
+
+ const ratio = size / Math.max(img.width, img.height);
+ const w = img.width * ratio;
+ const h = img.height * ratio;
+ canctx.drawImage(img, (size - w) / 2, (size - h) / 2, w, h);
+
+ cachedGraphics[key] = can;
+ }
+ ctx.drawImage(cachedGraphics[key], Math.round(x - size / 2), Math.round(y - size / 2),);
+}
+
+function drawText(ctx, text, color, fontSize, {x, y}) {
+ const key = "text" + text + "_" + color + "_" + fontSize;
+
+ if (!cachedGraphics[key]) {
+ const can = document.createElement("canvas");
+ can.width = fontSize * text.length;
+ can.height = fontSize;
+ const canctx = can.getContext("2d");
+ canctx.fillStyle = color;
+ canctx.textAlign = "center";
+ canctx.textBaseline = "middle";
+ canctx.font = fontSize + "px monospace";
+
+ canctx.fillText(text, can.width / 2, can.height / 2, can.width);
+
+ cachedGraphics[key] = can;
+ }
+ ctx.drawImage(cachedGraphics[key], Math.round(x - cachedGraphics[key].width / 2), Math.round(y - cachedGraphics[key].height / 2),);
+}
+
+function pixelsToPan(pan) {
+ return (pan - offsetX) / gameZoneWidth;
+}
+
+let lastComboPlayed = NaN, shepard = 6;
+
+function playShepard(delta, pan, volume) {
+ const shepardMax = 11, factor = 1.05945594920268, baseNote = 392;
+ shepard += delta;
+ if (shepard > shepardMax) shepard = 0;
+ if (shepard < 0) shepard = shepardMax;
+
+ const play = (note) => {
+ const freq = baseNote * Math.pow(factor, note);
+ const diff = Math.abs(note - shepardMax * 0.5);
+ const maxDistanceToIdeal = 1.5 * shepardMax;
+ const vol = Math.max(0, volume * (1 - diff / maxDistanceToIdeal));
+ createSingleBounceSound(freq, pan, vol);
+ return freq.toFixed(2) + " at " + Math.floor(vol * 100) + "% diff " + diff;
+ };
+
+ play(1 + shepardMax + shepard);
+ play(shepard);
+ play(-1 - shepardMax + shepard);
+}
+
+const sounds = {
+ wallBeep: (pan) => {
+ if (!isSettingOn("sound")) return;
+ createSingleBounceSound(800, pixelsToPan(pan));
+ },
+
+ comboIncreaseMaybe: (x, volume) => {
+ if (!isSettingOn("sound")) return;
+ let delta = 0;
+ if (!isNaN(lastComboPlayed)) {
+ if (lastComboPlayed < combo) delta = 1;
+ if (lastComboPlayed > combo) delta = -1;
+ }
+ playShepard(delta, pixelsToPan(x), volume);
+ lastComboPlayed = combo;
+ },
+
+ comboDecrease() {
+ if (!isSettingOn("sound")) return;
+ playShepard(-1, 0.5, 0.5);
+ }, coinBounce: (pan, volume) => {
+ if (!isSettingOn("sound")) return;
+ createSingleBounceSound(1200, pixelsToPan(pan), volume);
+ }, explode: (pan) => {
+ if (!isSettingOn("sound")) return;
+ createExplosionSound(pixelsToPan(pan));
+ }, revive: () => {
+ if (!isSettingOn("sound")) return;
+ createRevivalSound(500);
+ }, coinCatch(pan) {
+ if (!isSettingOn("sound")) return;
+ createSingleBounceSound(440, pixelsToPan(pan), .8)
+ }
+};
+
+// How to play the code on the leftconst context = new window.AudioContext();
+let audioContext, delayNode;
+
+function getAudioContext() {
+ if (!audioContext) {
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
+ }
+ return audioContext;
+}
+
+function createSingleBounceSound(baseFreq = 800, pan = 0.5, volume = 1, duration = 0.1,) {
+ const context = getAudioContext();
+ // Frequency for the metal "ping"
+ const baseFrequency = baseFreq; // Hz
+
+ // Create an oscillator for the impact sound
+ const oscillator = context.createOscillator();
+ oscillator.type = "sine";
+ oscillator.frequency.setValueAtTime(baseFrequency, context.currentTime);
+
+ // Create a gain node to control the volume
+ const gainNode = context.createGain();
+ oscillator.connect(gainNode);
+
+ // Create a stereo panner node for left-right panning
+ const panner = context.createStereoPanner();
+ panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
+ gainNode.connect(panner);
+ panner.connect(context.destination);
+
+ // Set up the gain envelope to simulate the impact and quick decay
+ gainNode.gain.setValueAtTime(0.8 * volume, context.currentTime); // Initial impact
+ gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + duration,); // Quick decay
+
+ // Start the oscillator
+ oscillator.start(context.currentTime);
+
+ // Stop the oscillator after the decay
+ oscillator.stop(context.currentTime + duration);
+}
+
+function createRevivalSound(baseFreq = 440) {
+ const context = getAudioContext();
+
+ // Create multiple oscillators for a richer sound
+ const oscillators = [context.createOscillator(), context.createOscillator(), context.createOscillator(),];
+
+ // Set the type and frequency for each oscillator
+ oscillators.forEach((osc, index) => {
+ osc.type = "sine";
+ osc.frequency.setValueAtTime(baseFreq + index * 2, context.currentTime); // Slight detuning
+ });
+
+ // Create a gain node to control the volume
+ const gainNode = context.createGain();
+
+ // Connect all oscillators to the gain node
+ oscillators.forEach((osc) => osc.connect(gainNode));
+
+ // Create a stereo panner node for left-right panning
+ const panner = context.createStereoPanner();
+ panner.pan.setValueAtTime(0, context.currentTime); // Center panning
+ gainNode.connect(panner);
+ panner.connect(context.destination);
+
+ // Set up the gain envelope to simulate a smooth attack and decay
+ gainNode.gain.setValueAtTime(0, context.currentTime); // Start at zero
+ gainNode.gain.linearRampToValueAtTime(0.8, context.currentTime + 0.5); // Ramp up to full volume
+ gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 2); // Slow decay
+
+ // Start all oscillators
+ oscillators.forEach((osc) => osc.start(context.currentTime));
+
+ // Stop all oscillators after the decay
+ oscillators.forEach((osc) => osc.stop(context.currentTime + 2));
+}
+
+let noiseBuffer;
+
+function createExplosionSound(pan = 0.5) {
+ const context = getAudioContext();
+ // Create an audio buffer
+ if (!noiseBuffer) {
+ const bufferSize = context.sampleRate * 2; // 2 seconds
+ noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate);
+ const output = noiseBuffer.getChannelData(0);
+
+ // Fill the buffer with random noise
+ for (let i = 0; i < bufferSize; i++) {
+ output[i] = Math.random() * 2 - 1;
+ }
+ }
+
+ // Create a noise source
+ const noiseSource = context.createBufferSource();
+ noiseSource.buffer = noiseBuffer;
+
+ // Create a gain node to control the volume
+ const gainNode = context.createGain();
+ noiseSource.connect(gainNode);
+
+ // Create a filter to shape the explosion sound
+ const filter = context.createBiquadFilter();
+ filter.type = "lowpass";
+ filter.frequency.setValueAtTime(1000, context.currentTime); // Set the initial frequency
+ gainNode.connect(filter);
+
+ // Create a stereo panner node for left-right panning
+ const panner = context.createStereoPanner();
+ panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime); // pan 0 to 1 maps to -1 to 1
+
+ // Connect filter to panner and then to the destination (speakers)
+ filter.connect(panner);
+ panner.connect(context.destination);
+
+ // Ramp down the gain to simulate the explosion's fade-out
+ gainNode.gain.setValueAtTime(1, context.currentTime);
+ gainNode.gain.exponentialRampToValueAtTime(0.01, context.currentTime + 1);
+
+ // Lower the filter frequency over time to create the "explosive" effect
+ filter.frequency.exponentialRampToValueAtTime(60, context.currentTime + 1);
+
+ // Start the noise source
+ noiseSource.start(context.currentTime);
+
+ // Stop the noise source after the sound has played
+ noiseSource.stop(context.currentTime + 1);
+}
+
+let levelTime = 0;
+
+setInterval(() => {
+ document.body.className = (running ? " running " : " paused ") + (currentLevelInfo().black_puck ? ' black_puck ' : ' ');
+}, 100);
+
+window.addEventListener("visibilitychange", () => {
+ if (document.hidden) {
+ pause()
+ }
+});
+
+const scoreDisplay = document.getElementById("score");
+
+
+function asyncAlert({
+ title,
+ text,
+ actions = [{text: "OK", value: "ok", help: ""}],
+ allowClose = true,
+ textAfterButtons = ''
+ }) {
+ return new Promise((resolve) => {
+ const popupWrap = document.createElement("div");
+ document.body.appendChild(popupWrap);
+ popupWrap.className = "popup";
+
+ function closeWithResult(value) {
+ resolve(value);
+ // Doing this async lets the menu scroll persist if it's shown a second time
+ setTimeout(() => {
+ document.body.removeChild(popupWrap);
+ });
+ }
+
+ if (allowClose) {
+ const closeButton = document.createElement("button");
+ closeButton.title = "close"
+ closeButton.className = "close-modale"
+ closeButton.addEventListener('click', (e) => {
+ e.preventDefault()
+ closeWithResult(null)
+ })
+ popupWrap.appendChild(closeButton)
+ }
+
+ const popup = document.createElement("div");
+
+ if (title) {
+ const p = document.createElement("h2");
+ p.innerHTML = title;
+ popup.appendChild(p);
+ }
+
+ if (text) {
+ const p = document.createElement("div");
+ p.innerHTML = text;
+ popup.appendChild(p);
+ }
+
+ actions.filter(i => i).forEach(({text, value, help, checked = 0, max = 0, disabled, icon = ''}) => {
+ const button = document.createElement("button");
+ let checkMark = ''
+ if (max) {
+ checkMark += ''
+ for (let i = 0; i < max; i++) {
+ checkMark += ' ';
+ }
+ checkMark += ' '
+ }
+ button.innerHTML = `
+${icon}
+${checkMark}
+
+ ${text}
+ ${help || ''}
+
`;
+
+
+ if (disabled) {
+ button.setAttribute("disabled", "disabled");
+ } else {
+ button.addEventListener("click", (e) => {
+ e.preventDefault();
+ closeWithResult(value)
+ });
+ }
+ popup.appendChild(button);
+ });
+
+ if (textAfterButtons) {
+ const p = document.createElement("div");
+ p.className = 'textAfterButtons'
+ p.innerHTML = textAfterButtons;
+ popup.appendChild(p);
+ }
+
+
+ popupWrap.appendChild(popup);
+ });
+}
+
+// Settings
+let cachedSettings = {};
+
+function isSettingOn(key) {
+ if (typeof cachedSettings[key] == "undefined") {
+ try {
+ cachedSettings[key] = JSON.parse(localStorage.getItem("breakout-settings-enable-" + key),);
+ } catch (e) {
+ console.warn(e);
+ }
+ }
+ return cachedSettings[key] ?? options[key]?.default ?? false;
+}
+
+function toggleSetting(key) {
+ cachedSettings[key] = !isSettingOn(key);
+ try {
+ const lskey = "breakout-settings-enable-" + key;
+ localStorage.setItem(lskey, JSON.stringify(cachedSettings[key]));
+ } catch (e) {
+ console.warn(e);
+ }
+ if (options[key].afterChange) options[key].afterChange();
+}
+
+scoreDisplay.addEventListener("click", async (e) => {
+ e.preventDefault();
+ running = false
+ const cb = await asyncAlert({
+ title: ` ${score} points at level ${currentLevel + 1} / ${max_levels()}`,
+ text: `
+ ${pickedUpgradesHTMl()}
+ ${scoreStory.map((t) => "" + t + "
").join("")}
+
+ `, allowClose: true, actions: [{
+ text: "New run", help: "Start a brand new run.", value: () => {
+ restart();
+ return true;
+ },
+ }],
+ });
+ if (cb) {
+ await cb()
+ }
+});
+
+document.getElementById("menu").addEventListener("click", (e) => {
+ e.preventDefault();
+ openSettingsPanel();
+});
+
+const options = {
+ sound: {
+ default: true, name: `Game sounds`, help: `Can slow down some phones.`,
+ }, "mobile-mode": {
+ default: window.innerHeight > window.innerWidth,
+ name: `Mobile mode`,
+ help: `Leaves space for your thumb.`,
+ afterChange() {
+ fitSize();
+ },
+ },
+ basic: {
+ default: false, name: `Fast mode`, help: `Simpler graphics for older devices.`,
+ },
+ "easy": {
+ default: false, name: `Easy mode`, help: `Slower ball as starting perk.`, restart: true,
+ }, "color_blind": {
+ default: false, name: `Color blind mode`, help: `Removes mechanics about colors.`, restart: true,
+ },
+};
+
+async function openSettingsPanel() {
+ pause()
+
+ const optionsList = [];
+ for (const key in options) {
+ optionsList.push({
+ checked: isSettingOn(key) ? 1 : 0, max: 1, text: options[key].name, help: options[key].help, value: () => {
+ toggleSetting(key)
+ if (options[key].restart) {
+ restart()
+ } else {
+ openSettingsPanel();
+ }
+ },
+ });
+ }
+
+ const cb = await asyncAlert({
+ title: "Breakout 71", text: `
+ `, allowClose: true, actions: [
+ {
+ text: 'Unlocks',
+ help: "See and try what you've unlocked",
+ async value() {
+ const ts = getTotalScore()
+ const actions=[...upgrades
+ .sort((a, b) => a.threshold - b.threshold)
+ .map(({
+ name,
+ max,
+ help, id,
+ threshold, icon
+ }) => ({
+ text: name,
+ help: ts >= threshold ? help :`Unlocks at total score ${threshold}.`,
+ disabled: ts < threshold,
+ value: {perks: {[id]: 1}},
+ icon
+ })
+ )
+
+ ,
+ ...allLevels
+ .sort((a, b) => a.threshold - b.threshold)
+ .map((l, li) => {
+ const avaliable = ts >= l.threshold
+ return ({
+ text: l.name,
+ help: avaliable ? `A ${l.size}x${l.size} level with ${l.bricks.filter(i => i).length} bricks` : `Unlocks at total score ${l.threshold}.`,
+ disabled: !avaliable,
+ value: {level: l.name},
+ icon: levelIconHTML(l)
+ })
+ })
+ ]
+
+ const tryOn = await asyncAlert({
+ title: `You unlocked ${Math.round(actions.filter(a=>!a.disabled).length / actions.length * 100)}% of the game.`,
+ text: `
+ Your total score is ${ts}. Below are all the upgrades and levels the games has to offer. They greyed out ones can be unlocked by increasing your total score.
+ `,
+ textAfterButtons:`
+The total score increases every time you score in game.
+Your high score is ${highScore}.
+Click an item above to start a test run with it.
+
`,
+ actions
+
+
+ ,
+ allowClose: true,
+ })
+ if (tryOn) {
+ nextRunOverrides = tryOn
+ restart()
+ }
+ }
+ },
+
+ ...optionsList,
+
+ (window.screenTop || window.screenY) && {
+ text: "Fullscreen",
+ help: "Might not work on some machines",
+ value() {
+ const docel = document.documentElement
+ if (docel.requestFullscreen) {
+ docel.requestFullscreen();
+ } else if (docel.webkitRequestFullscreen) {
+ docel.webkitRequestFullscreen();
+ }
+ }
+ },
+ {
+ text: 'Reset Game',
+ help: "Erase high score and statistics",
+ async value() {
+ if (await asyncAlert({
+ title: 'Reset',
+ actions: [
+ {
+ text: 'Yes',
+ value: true
+ },
+ {
+ text: 'No',
+ value: false
+ }
+ ],
+ allowClose: true,
+ })) {
+ localStorage.clear()
+ window.location.reload()
+ }
+
+ }
+ }
+ ],
+ textAfterButtons: `
+ Made in France by Renan LE CARO
+ privacy policy -
+ Google Play -
+ itch.io
+
+
+ `
+ })
+ if (cb) {
+ cb()
+ }
+}
+
+function distance2(a, b) {
+ return Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2)
+}
+
+function distanceBetween(a, b) {
+ return Math.sqrt(distance2(a, b))
+}
+
+function rainbowColor() {
+ return `hsl(${(levelTime / 2) % 360},100%,70%)`
+}
+
+function repulse(a, b, power, impactsBToo) {
+
+ const distance = distanceBetween(a, b)
+ // Ensure we don't get soft locked
+ const max = gameZoneWidth / 2
+ if (distance > max) return
+ // Unit vector
+ const dx = (a.x - b.x) / distance
+ const dy = (a.y - b.y) / distance
+ // TODO
+
+ const fact = -power * (max - distance) / (max * 1.2) / 3 * Math.min(500, levelTime) / 500
+ if (impactsBToo) {
+ b.vx += dx * fact
+ b.vy += dy * fact
+ }
+ a.vx -= dx * fact
+ a.vy -= dy * fact
+
+ if (!isSettingOn('basic')) {
+ const speed = 10
+ const rand = 2
+ flashes.push({
+ type: "particle",
+ duration: 100,
+ time: levelTime,
+ size: coinSize / 2,
+ color: rainbowColor(),
+ ethereal: true,
+ x: a.x,
+ y: a.y,
+ vx: -dx * speed + a.vx + (Math.random() - 0.5) * rand,
+ vy: -dy * speed + a.vy + (Math.random() - 0.5) * rand,
+ })
+ if (impactsBToo) {
+
+ flashes.push({
+ type: "particle",
+ duration: 100,
+ time: levelTime,
+ size: coinSize / 2,
+ color: rainbowColor(),
+ ethereal: true,
+ x: b.x,
+ y: b.y,
+ vx: dx * speed + b.vx + (Math.random() - 0.5) * rand,
+ vy: dy * speed + b.vy + (Math.random() - 0.5) * rand,
+ })
+ }
+ }
+
+}
+
+function attract(a, b, power) {
+
+ const distance = distanceBetween(a, b)
+ // Ensure we don't get soft locked
+ const min = gameZoneWidth * .5
+ if (distance < min) return
+ // Unit vector
+ const dx = (a.x - b.x) / distance
+ const dy = (a.y - b.y) / distance
+
+ const fact = power * (distance - min) / min * Math.min(500, levelTime) / 500
+ b.vx += dx * fact
+ b.vy += dy * fact
+ a.vx -= dx * fact
+ a.vy -= dy * fact
+
+ if (!isSettingOn('basic')) {
+ const speed = 10
+ const rand = 2
+ flashes.push({
+ type: "particle",
+ duration: 100,
+ time: levelTime,
+ size: coinSize / 2,
+ color: rainbowColor(),
+ ethereal: true,
+ x: a.x,
+ y: a.y,
+ vx: dx * speed + a.vx + (Math.random() - 0.5) * rand,
+ vy: dy * speed + a.vy + (Math.random() - 0.5) * rand,
+ })
+ flashes.push({
+ type: "particle",
+ duration: 100,
+ time: levelTime,
+ size: coinSize / 2,
+ color: rainbowColor(),
+ ethereal: true,
+ x: b.x,
+ y: b.y,
+ vx: -dx * speed + b.vx + (Math.random() - 0.5) * rand,
+ vy: -dy * speed + b.vy + (Math.random() - 0.5) * rand,
+ })
+ }
+}
+
+let levelIconHTMLCanvas = document.createElement('canvas')
+const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", {antialias: false, alpha: true})
+
+function levelIconHTML(level, title) {
+ const size=40
+ const c = levelIconHTMLCanvas
+ const ctx = levelIconHTMLCanvasCtx
+ c.width = size
+ c.height = size
+ if (level.color) {
+ ctx.fillStyle = level.color
+ ctx.fillRect(0, 0, size, size)
+ } else {
+ ctx.clearRect(0, 0, size, size)
+ }
+ const pxSize = size / level.size
+ for (let x = 0; x < level.size; x++) {
+ for (let y = 0; y < level.size; y++) {
+ const c = level.bricks[y * level.size + x]
+ if (c) {
+ ctx.fillStyle = c
+ ctx.fillRect(Math.floor(pxSize * x), Math.floor(pxSize * y), Math.ceil(pxSize), Math.ceil(pxSize))
+ }
+ }
+ }
+ // I don't think many blind people will benefit for this but it's nice to have something to put in "alt"
+ return ` `
+}
+
+upgrades.forEach(u => u.icon = levelIconHTML(perkIconsLevels[u.id], u.name))
+
+fitSize()
+restart()
+tick();
\ No newline at end of file
diff --git a/app/src/main/assets/icon.svg b/app/src/main/assets/icon.svg
new file mode 100644
index 0000000..f411508
--- /dev/null
+++ b/app/src/main/assets/icon.svg
@@ -0,0 +1,146 @@
+
+
+
+
diff --git a/app/src/main/assets/index.html b/app/src/main/assets/index.html
index aa62233..bcce3ba 100644
--- a/app/src/main/assets/index.html
+++ b/app/src/main/assets/index.html
@@ -1 +1,21 @@
-Breakout 71
\ No newline at end of file
+
+
+
+
+
+
+ Breakout 71
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/levels.js b/app/src/main/assets/levels.js
new file mode 100644
index 0000000..fc1c822
--- /dev/null
+++ b/app/src/main/assets/levels.js
@@ -0,0 +1,9126 @@
+let allLevels=[
+ {
+ "name": "71 mini",
+ "size": 5,
+ "bricks": [
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Butterfly",
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "size": 9,
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Castle",
+ "size": 7,
+ "bricks": [
+ "#E67070",
+ "",
+ "#E67070",
+ "",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "black",
+ "black",
+ "black",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "black",
+ "black",
+ "black",
+ "#E67070",
+ "#E67070",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#5DA3EA"
+ ],
+ "svg": " ",
+ "focus": false
+ },
+ {
+ "name": "Eyes",
+ "size": 9,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ "#5DA3EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ null,
+ "#5DA3EA",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ null,
+ "#5DA3EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false,
+ "squared": true
+ },
+ {
+ "name": "Creeper",
+ "size": 10,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#59EEA3",
+ "#59EEA3",
+ "#A1F051",
+ "#A1F051",
+ "#59EEA3",
+ "#59EEA3",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "#59EEA3",
+ "#A1F051",
+ "#59EEA3",
+ "#59EEA3",
+ "#A1F051",
+ "#59EEA3",
+ "#A1F051",
+ "#59EEA3",
+ "",
+ "",
+ "#A1F051",
+ "black",
+ "black",
+ "#59EEA3",
+ "#59EEA3",
+ "black",
+ "black",
+ "#59EEA3",
+ "",
+ "",
+ "#59EEA3",
+ "black",
+ "black",
+ "#A1F051",
+ "#59EEA3",
+ "black",
+ "black",
+ "#59EEA3",
+ "",
+ "",
+ "#A1F051",
+ "#59EEA3",
+ "#59EEA3",
+ "black",
+ "black",
+ "#A1F051",
+ "#A1F051",
+ "#59EEA3",
+ "",
+ "",
+ "#59EEA3",
+ "#59EEA3",
+ "black",
+ "black",
+ "black",
+ "black",
+ "#59EEA3",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "black",
+ "black",
+ "black",
+ "black",
+ "#59EEA3",
+ "#A1F051",
+ "",
+ "",
+ "#59EEA3",
+ "#A1F051",
+ "black",
+ "#59EEA3",
+ "#59EEA3",
+ "black",
+ "#A1F051",
+ "#59EEA3",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false
+ },
+ {
+ "name": "Stairs",
+ "size": 8,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ "#A664E8",
+ "#A664E8",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ "#A664E8",
+ "#A664E8",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ "#E869E8",
+ "#E869E8",
+ "#A664E8",
+ "#A664E8",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#E869E8",
+ "#E869E8",
+ "#A664E8",
+ "#A664E8",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA"
+ ],
+ "svg": " ",
+ "focus": false
+ },
+ {
+ "name": "Dots",
+ "size": 9,
+ "bricks": [
+ "#6262EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5BECEC",
+ null,
+ "#59EEA3",
+ null,
+ "#53EE53",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#6262EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5BECEC",
+ null,
+ "#59EEA3",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#A664E8",
+ null,
+ "#6262EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5BECEC",
+ null,
+ "#59EEA3",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#A664E8",
+ null,
+ "#6262EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5BECEC",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E869E8",
+ null,
+ "#A664E8",
+ null,
+ "#6262EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5BECEC"
+ ],
+ "svg": " ",
+ "focus": false
+ },
+ {
+ "name": "Lines",
+ "size": 9,
+ "bricks": [
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Heart",
+ "size": 15,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ null,
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "white",
+ "white",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ null,
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "white",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ null,
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ null,
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "white",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ null,
+ "",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#F44848",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ ""
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Swiss",
+ "size": 7,
+ "bricks": [
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ null,
+ null,
+ "#ab0c0c",
+ "#ab0c0c",
+ "white",
+ "#ab0c0c",
+ "#ab0c0c",
+ null,
+ null,
+ "#ab0c0c",
+ "white",
+ "white",
+ "white",
+ "#ab0c0c",
+ null,
+ null,
+ "#ab0c0c",
+ "#ab0c0c",
+ "white",
+ "#ab0c0c",
+ "#ab0c0c",
+ null,
+ null,
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false,
+ "squared": true
+ },
+ {
+ "name": "Germany",
+ "size": 6,
+ "bricks": [
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": "",
+ "squared": false,
+ "color": "#ffffff",
+ "focus": false,
+ "black_puck": true
+ },
+ {
+ "name": "France",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Smiley",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Labyrinthe",
+ "size": 11,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#F44848",
+ "",
+ "#F44848",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#F44848",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "#F44848",
+ null,
+ "",
+ "#F44848",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#F44848",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#F44848",
+ "",
+ "#F44848",
+ "",
+ "",
+ null,
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#F44848",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#F44848",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#F44848",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#F44848",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#F44848"
+ ],
+ "svg": " ",
+ "focus": false
+ },
+ {
+ "name": "Temple",
+ "size": 11,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "#A664E8",
+ "",
+ "#A664E8",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "#E66BA8",
+ "",
+ "#E66BA8",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Pacman",
+ "size": 12,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "black",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#F44848",
+ "",
+ "#F44848",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Ship",
+ "size": 11,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "",
+ "",
+ "",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "",
+ "#F29E4A",
+ "black",
+ "#F29E4A",
+ "black",
+ "#F29E4A",
+ "black",
+ "#F29E4A",
+ "black",
+ "#F29E4A",
+ "#F29E4A",
+ "",
+ "",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ null,
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#333",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#333",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#333",
+ "#333",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#333",
+ "#333",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA"
+ ],
+ "svg": " ",
+ "focus": false
+ },
+ {
+ "name": "We come in peace",
+ "size": 13,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "black",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "black",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ null,
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ null,
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ null,
+ "",
+ "#5BECEC",
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ "#5BECEC",
+ null,
+ "",
+ "#5BECEC",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "#5BECEC",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Space mushroom",
+ "size": 10,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ null,
+ "",
+ "white",
+ "white",
+ "black",
+ "white",
+ "white",
+ "black",
+ "white",
+ "white",
+ null,
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ null,
+ "",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "white",
+ "",
+ "white",
+ "white",
+ "",
+ "white",
+ "",
+ null,
+ "",
+ "white",
+ "",
+ "white",
+ "",
+ "",
+ "white",
+ "",
+ "white"
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Wololo",
+ "size": 9,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "",
+ "#F29E4A",
+ "#F29E4A",
+ "white",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "",
+ "",
+ "#F29E4A",
+ "white",
+ "white",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ "",
+ "#F29E4A",
+ "white",
+ "white",
+ "white",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "white",
+ "",
+ "white",
+ "white",
+ "white",
+ "",
+ "white",
+ "#6262EA",
+ "white",
+ "",
+ "white",
+ "#F29E4A",
+ "white",
+ "",
+ "",
+ "white",
+ "white",
+ "#6262EA",
+ "",
+ "",
+ "#F29E4A",
+ "white",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "#F29E4A",
+ "",
+ "",
+ "",
+ "white",
+ "",
+ "white",
+ "",
+ "",
+ "#F29E4A",
+ "",
+ "",
+ "",
+ "white",
+ "",
+ "white",
+ "",
+ "",
+ "#F29E4A"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Small heart",
+ "size": 15,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "white",
+ "white",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "#ab0c0c",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "#ab0c0c",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#e32119",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Eye",
+ "size": 9,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#231f20",
+ "white",
+ "white",
+ "white",
+ "#231f20",
+ "",
+ "",
+ "",
+ "#231f20",
+ "white",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "white",
+ "#231f20",
+ "",
+ "#231f20",
+ "white",
+ "white",
+ "#6262EA",
+ "black",
+ "#6262EA",
+ "white",
+ "white",
+ "#231f20",
+ "",
+ "#231f20",
+ "white",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "white",
+ "#231f20",
+ "",
+ "",
+ "",
+ "#231f20",
+ "white",
+ "white",
+ "white",
+ "#231f20",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "color": "#99c1f1",
+ "focus": false
+ },
+ {
+ "name": "Enderman",
+ "size": 10,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "#A664E8",
+ "#A664E8",
+ "#A664E8",
+ "#231f20",
+ "#231f20",
+ "#A664E8",
+ "#A664E8",
+ "#A664E8",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "color": "#ffffff",
+ "focus": false,
+ "squared": true,
+ "black_puck": true
+ },
+ {
+ "name": "Mushroom",
+ "size": 16,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "#e32119",
+ "",
+ "",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "#e32119",
+ "",
+ "",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "black",
+ "white",
+ "white",
+ "black",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "black",
+ "white",
+ "white",
+ "black",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false,
+ "black_puck": false,
+ "squared": true
+ },
+ {
+ "name": "Tulip",
+ "size": 11,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "",
+ "#ab0c0c",
+ "",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ab0c0c",
+ "#ab0c0c",
+ "#ab0c0c",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Chain",
+ "size": 7,
+ "bricks": [
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "black",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "black",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "black",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Marion",
+ "size": 9,
+ "bricks": [
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119"
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Renan",
+ "size": 9,
+ "bricks": [
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Violet Pairs",
+ "size": 8,
+ "bricks": [
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA",
+ null,
+ "#6262EA"
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Red Cups",
+ "size": 11,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "#e32119",
+ "black",
+ "#e32119",
+ "",
+ "#e32119",
+ "black",
+ "#e32119",
+ "",
+ "#e32119",
+ "black",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "#e32119",
+ "",
+ "#e32119",
+ "black",
+ "#e32119",
+ "",
+ "#e32119",
+ "black",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "#e32119",
+ "black",
+ "#e32119",
+ "",
+ "#e32119",
+ "black",
+ "#e32119",
+ "",
+ "#e32119",
+ "black",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Cactus",
+ "size": 10,
+ "bricks": [
+ null,
+ "",
+ "",
+ "",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#A1F051",
+ "",
+ "#A1F051",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "",
+ "#A1F051",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#618227",
+ "#A1F051",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#A1F051",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Sunny Face",
+ "size": 11,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "white",
+ "white",
+ "#ffd300",
+ "white",
+ "white",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "white",
+ "white",
+ "white",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": "",
+ "focus": false,
+ "color": "#62a0ea",
+ "squared": true
+ },
+ {
+ "name": "Mountain",
+ "size": 9,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "white",
+ "white",
+ "",
+ "",
+ "white",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Dollar",
+ "size": 17,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "color": "#f6d32d",
+ "focus": false
+ },
+ {
+ "name": "Waves",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5BECEC",
+ "#5BECEC",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5BECEC",
+ "#5BECEC",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Box",
+ "size": 8,
+ "bricks": [
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false,
+ "squared": false
+ },
+ {
+ "name": "Rose",
+ "size": 9,
+ "bricks": [
+ "",
+ "",
+ "#F44848",
+ "#F44848",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#F44848",
+ "#F44848",
+ "",
+ "#618227",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#618227",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "#618227",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#618227"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Time",
+ "size": 9,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "#ffd300",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "white",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false,
+ "squared": false
+ },
+ {
+ "name": "Watermelon",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#F44848",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#F44848",
+ "#F44848",
+ "black",
+ "#618227",
+ "",
+ "",
+ "",
+ "#F44848",
+ "black",
+ "#F44848",
+ "#F44848",
+ "#618227",
+ "",
+ "",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#618227",
+ "",
+ "#F44848",
+ "#F44848",
+ "black",
+ "#F44848",
+ "#F44848",
+ "#618227",
+ "",
+ "#F44848",
+ "black",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#618227",
+ "",
+ "#618227",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Worms",
+ "size": 13,
+ "bricks": [
+ null,
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "#E67070",
+ "white",
+ "white",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "black",
+ "#E67070",
+ "black",
+ "white",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "black",
+ "#E67070",
+ "black",
+ "white",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "#E67070",
+ "white",
+ "white",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "#E67070",
+ "#E67070",
+ "white",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false,
+ "squared": false
+ },
+ {
+ "name": "Ocean Sunrise",
+ "size": 8,
+ "bricks": [
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ffd300",
+ "#ffd300",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#F44848",
+ "#F44848",
+ "#F44848",
+ "#ffd300",
+ "#ffd300",
+ "white",
+ "white",
+ "#ffd300",
+ "#ffd300",
+ "#F44848",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5BECEC",
+ "#5BECEC",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA"
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Crosses",
+ "size": 13,
+ "bricks": [
+ "#6262EA",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "#A664E8",
+ "#A664E8",
+ "",
+ "#A664E8",
+ "#A664E8",
+ "#A664E8",
+ "",
+ "#A664E8",
+ "#A664E8",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "",
+ "#A664E8",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "",
+ "",
+ "",
+ "#E869E8"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Negative space",
+ "size": 9,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "UK",
+ "size": 11,
+ "bricks": [
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "white",
+ "#e32119",
+ "white",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "white",
+ "#e32119",
+ "white",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "white",
+ "#e32119",
+ "white",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "white",
+ "#e32119",
+ "white",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "white",
+ "#e32119",
+ "white",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "#6262EA",
+ "white",
+ "#e32119",
+ "white",
+ "#6262EA",
+ "#6262EA",
+ "#e32119",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Greece",
+ "size": 11,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "squared": true,
+ "color": ""
+ },
+ {
+ "name": "Russia",
+ "size": 8,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "squared": true,
+ "color": ""
+ },
+ {
+ "name": "Ukraine",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": ""
+ },
+ {
+ "name": "Poland",
+ "size": 7,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": "",
+ "squared": true
+ },
+ {
+ "name": "Yellow 71",
+ "size": 9,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "71 on white",
+ "size": 6,
+ "bricks": [
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "#e32119",
+ "#e32119",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "Blue 71",
+ "size": 8,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ null,
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ null,
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ "#6262EA",
+ "#6262EA",
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ "#6262EA",
+ "#6262EA",
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ null,
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ null,
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ "#6262EA",
+ "#6262EA"
+ ],
+ "svg": " ",
+ "color": "",
+ "focus": false
+ },
+ {
+ "name": "Seventy one",
+ "size": 21,
+ "bricks": [
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "#e32119",
+ null,
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "#e32119",
+ null,
+ "#e32119",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "#e32119",
+ null,
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#e32119",
+ null,
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "#e32119",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "B71",
+ "size": 10,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "",
+ "",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "",
+ "",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "",
+ "",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "",
+ "",
+ "#e32119",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "Pig",
+ "size": 9,
+ "bricks": [
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "",
+ "white",
+ "white",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "white",
+ "white",
+ "",
+ "",
+ "white",
+ "black",
+ "#E66BA8",
+ "#E66BA8",
+ "#E66BA8",
+ "black",
+ "white",
+ "",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "",
+ "#E66BA8",
+ "#E67070",
+ "black",
+ "#E67070",
+ "black",
+ "#E67070",
+ "#E66BA8",
+ "",
+ "",
+ "#E66BA8",
+ "#E66BA8",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E66BA8",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "Big Pig",
+ "size": 15,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "white",
+ "black",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "black",
+ "white",
+ "#E67070",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "black",
+ "black",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "black",
+ "black",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "#E67070",
+ "black",
+ "#E67070",
+ "black",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#E67070",
+ "#A1F051",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#E67070",
+ "#A1F051",
+ "#E67070",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#E67070",
+ "#E67070",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#E67070",
+ "#E67070",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": " ",
+ "focus": false,
+ "color": "",
+ "squared": true
+ },
+ {
+ "name": "Donkey Kong",
+ "size": 9,
+ "bricks": [
+ "#F29E4A",
+ "#F29E4A",
+ "#e32119",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "#F29E4A",
+ "#F29E4A",
+ "#e32119",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ "#F29E4A",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#e32119",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "#F29E4A",
+ "",
+ "",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "#E869E8",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false,
+ "color": "#241f31"
+ },
+ {
+ "name": "Banana",
+ "size": 12,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#e1c8b4",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#53EE53",
+ "",
+ null,
+ "",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "#53EE53",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300"
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "Fox",
+ "size": 8,
+ "bricks": [
+ "#e1c8b4",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "",
+ "#F29E4A",
+ "#F29E4A",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#F29E4A",
+ "black",
+ "#F29E4A",
+ "#F29E4A",
+ "black",
+ "#F29E4A",
+ "#e1c8b4",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "",
+ "white",
+ "white",
+ "black",
+ "black",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false,
+ "squared": true
+ },
+ {
+ "name": "Wiki",
+ "size": 10,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#618227",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#618227",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ "#231f20",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#231f20",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ "#618227",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#618227",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "Baby Dog",
+ "size": 8,
+ "bricks": [
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "",
+ "",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e1c8b4",
+ "#e1c8b4",
+ "white",
+ "#e1c8b4",
+ "white",
+ "white",
+ "white",
+ "#e1c8b4",
+ "#333",
+ "white",
+ "#e1c8b4",
+ "#333",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "#e1c8b4",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e1c8b4",
+ "#e1c8b4",
+ null,
+ "#e1c8b4",
+ "white",
+ "#333",
+ "#333",
+ "white",
+ "#e1c8b4",
+ null,
+ null,
+ "#e1c8b4",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#e1c8b4",
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "white"
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "Cute dog",
+ "size": 9,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "#F29E4A",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#F29E4A",
+ "",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "white",
+ "white",
+ "white",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#F29E4A",
+ "#e1c8b4",
+ "white",
+ "white",
+ "white",
+ "white",
+ "#F29E4A",
+ "#F29E4A",
+ "",
+ "#e1c8b4",
+ "black",
+ "#e1c8b4",
+ "white",
+ "white",
+ "black",
+ "white",
+ "",
+ "",
+ "#e1c8b4",
+ "black",
+ "#e1c8b4",
+ "white",
+ "white",
+ "black",
+ "white",
+ "",
+ "",
+ "",
+ "#e1c8b4",
+ "white",
+ "black",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "#ab0c0c",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "focus": false
+ },
+ {
+ "name": "perk:extra_life",
+ "size": 9,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:streak_shots",
+ "size": 8,
+ "bricks": [
+ "",
+ "white",
+ null,
+ "white",
+ "",
+ "white",
+ null,
+ null,
+ "white",
+ "",
+ "white",
+ null,
+ "white",
+ "",
+ "white",
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "white",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ "white",
+ null,
+ null,
+ "",
+ null,
+ null,
+ null,
+ "white",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white",
+ "white"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:base_combo",
+ "size": 8,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#ffd300",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:slow_down",
+ "size": 10,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "black",
+ "#A1F051",
+ "",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#618227",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:bigger_puck",
+ "size": 8,
+ "bricks": [
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ "white",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:viscosity",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#5DA3EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#ffd300",
+ "#6262EA",
+ "#6262EA",
+ "#ffd300",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:sides_are_lava",
+ "size": 8,
+ "bricks": [
+ "#e32119",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#e32119",
+ "#e32119",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#e32119",
+ "#e32119",
+ null,
+ "",
+ "",
+ "",
+ "",
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ null,
+ "white",
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ "white",
+ "white",
+ "white",
+ null,
+ null,
+ "#e32119"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:telekinesis",
+ "size": 8,
+ "bricks": [
+ "",
+ null,
+ null,
+ null,
+ null,
+ "#E66BA8",
+ "white",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E67070",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E66BA8",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E67070",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E66BA8",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E67070",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E66BA8",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white",
+ "white",
+ "white"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:top_is_lava",
+ "size": 8,
+ "bricks": [
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ null,
+ "white",
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ null,
+ "white",
+ "white",
+ "white",
+ null,
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:coin_magnet",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "#ffd300",
+ null,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ null,
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "",
+ null,
+ null,
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ null,
+ "",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:skip_last",
+ "size": 5,
+ "bricks": [
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:multiball",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ null,
+ "white",
+ "white",
+ "white",
+ "",
+ null,
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:smaller_puck",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ null,
+ null,
+ null,
+ "white",
+ null,
+ null,
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ null,
+ "white",
+ "white",
+ null,
+ null,
+ null,
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:pierce",
+ "size": 6,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:picky_eater",
+ "size": 8,
+ "bricks": [
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ "#e32119",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white",
+ "white"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:metamorphosis",
+ "size": 8,
+ "bricks": [
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ "",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "#5BECEC",
+ "",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5BECEC",
+ "#5BECEC",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:catch_all_coins",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ "#ffd300",
+ "",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ null,
+ null,
+ "white",
+ null,
+ null,
+ "#ffd300",
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "#e32119",
+ "#e32119",
+ "white",
+ "white",
+ "white",
+ "#e32119",
+ "#e32119",
+ "#e32119"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:hot_start",
+ "size": 7,
+ "bricks": [
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#ffd300",
+ "",
+ "",
+ "white",
+ "white",
+ "white",
+ "",
+ "",
+ "#ffd300"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:sapper",
+ "size": 9,
+ "bricks": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "white",
+ null,
+ null,
+ "",
+ "",
+ "",
+ "",
+ "white",
+ "",
+ "",
+ "white",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "white",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#ffd300",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": "",
+ "color": "#000000"
+ },
+ {
+ "name": "perk:bigger_explosions",
+ "size": 8,
+ "bricks": [
+ "",
+ null,
+ "#e32119",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#e32119",
+ "#ffd300",
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ "#e32119",
+ "#ffd300",
+ "#e32119",
+ "#ffd300",
+ "",
+ null,
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ "white",
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ "#e32119",
+ "#e32119",
+ "white",
+ "#ffd300",
+ "#ffd300",
+ "#ffd300",
+ null,
+ null,
+ null,
+ "#ffd300",
+ "#e32119",
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ "#ffd300",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ "#e32119",
+ "#e32119"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:extra_levels",
+ "size": 6,
+ "bricks": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:pierce_color",
+ "size": 8,
+ "bricks": [
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:soft_reset",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "",
+ "#e32119",
+ "#231f20",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "white",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#e32119",
+ "#e32119",
+ "#ffd300",
+ "white",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "#e32119",
+ "#ffd300",
+ "#ffd300",
+ "#231f20",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#231f20",
+ "#231f20",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#e32119",
+ "#231f20",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:ball_repulse_ball",
+ "size": 8,
+ "bricks": [
+ "white",
+ "#E67070",
+ "#E66BA8",
+ null,
+ null,
+ "#E66BA8",
+ "#E67070",
+ "white",
+ "#E67070",
+ "",
+ "",
+ null,
+ null,
+ "",
+ "",
+ "#E67070",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E66BA8",
+ "",
+ "",
+ null,
+ null,
+ null,
+ "",
+ null,
+ "",
+ null,
+ "",
+ "",
+ null,
+ null,
+ "",
+ null,
+ "",
+ "#E66BA8",
+ "",
+ "",
+ "",
+ null,
+ "",
+ "",
+ "#E66BA8",
+ "#E67070",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#E67070",
+ "white",
+ "#E67070",
+ "#E66BA8",
+ null,
+ "",
+ "#E66BA8",
+ "#E67070",
+ "white"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:ball_attract_ball",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "#E66BA8",
+ null,
+ "",
+ "#E66BA8",
+ null,
+ null,
+ "",
+ "",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ null,
+ null,
+ "#E66BA8",
+ "#E67070",
+ "white",
+ "",
+ null,
+ "white",
+ "#E67070",
+ "#E66BA8",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E66BA8",
+ "#E67070",
+ "white",
+ null,
+ null,
+ "white",
+ "#E67070",
+ "#E66BA8",
+ null,
+ "",
+ "#E67070",
+ "",
+ "",
+ "#E67070",
+ null,
+ "",
+ null,
+ null,
+ "#E66BA8",
+ "",
+ null,
+ "#E66BA8",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "perk:puck_repulse_ball",
+ "size": 8,
+ "bricks": [
+ "",
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ null,
+ null,
+ null,
+ null,
+ "white",
+ null,
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#E67070",
+ null,
+ null,
+ "",
+ "white",
+ null,
+ null,
+ null,
+ "#E66BA8",
+ "",
+ "",
+ "#E67070",
+ null,
+ null,
+ null,
+ null,
+ "",
+ "",
+ "#E66BA8",
+ "",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ null,
+ null,
+ null,
+ "white",
+ "white",
+ "white",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "A",
+ "size": 7,
+ "bricks": [
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "B",
+ "size": 9,
+ "bricks": [
+ null,
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "#6262EA",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "svg": ""
+ },
+ {
+ "name": "C",
+ "size": 8,
+ "bricks": [
+ "",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ null,
+ null,
+ null,
+ "#e32119",
+ "#e32119",
+ "#e32119",
+ "#e32119"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "D",
+ "size": 8,
+ "bricks": [
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ null,
+ null,
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ null,
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ null,
+ null,
+ "#A1F051",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ null,
+ null,
+ "#A1F051",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ "",
+ "",
+ "#A1F051",
+ null,
+ "",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051",
+ "#A1F051"
+ ],
+ "svg": ""
+ },
+ {
+ "name": "e",
+ "size": 8,
+ "bricks": [
+ "",
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ null,
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ "",
+ "",
+ "#5DA3EA",
+ "#5DA3EA",
+ null,
+ null,
+ null,
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ "#5DA3EA",
+ ""
+ ],
+ "svg": ""
+ }
+]
\ No newline at end of file
diff --git a/public/privacy.html b/app/src/main/assets/privacy.html
similarity index 80%
rename from public/privacy.html
rename to app/src/main/assets/privacy.html
index f5c3d6b..754cb9b 100644
--- a/public/privacy.html
+++ b/app/src/main/assets/privacy.html
@@ -8,7 +8,7 @@
/>
Breakout 71 privacy policy
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-