From 4c324d211cbd691ead170862d3a6a828f4081c93 Mon Sep 17 00:00:00 2001 From: Renan LE CARO Date: Sat, 26 Apr 2025 22:40:32 +0200 Subject: [PATCH] Build 29095000 --- Credits.md | 0 Readme.md | 2 + app/build.gradle.kts | 4 +- app/src/main/assets/index.html | 2 +- dist/index.html | 22 +- src/PWA/sw-b71.js | 2 +- src/creative.ts | 11 +- src/data/unlockConditions.json | 1371 +++++----------------------- src/data/unlockConditions.test.ts | 71 +- src/data/version.json | 2 +- src/game.less | 10 +- src/game.ts | 2 +- src/gameOver.ts | 10 +- src/gameStateMutators.ts | 3 +- src/game_utils.ts | 23 +- src/get_level_unlock_condition.ts | 190 ++-- src/levelEditor.ts | 30 +- src/level_editor/levels_editor.tsx | 2 +- src/migrations.ts | 7 +- src/monitorLevelsUnlocks.ts | 10 +- src/newGameState.ts | 5 +- src/openScorePanel.ts | 23 +- src/options.ts | 6 +- src/render.ts | 10 +- src/tooltip.ts | 9 +- src/types.d.ts | 19 +- src/upgrades.ts | 4 +- 27 files changed, 500 insertions(+), 1350 deletions(-) delete mode 100644 Credits.md diff --git a/Credits.md b/Credits.md deleted file mode 100644 index e69de29..0000000 diff --git a/Readme.md b/Readme.md index b045a2a..4fa1c36 100644 --- a/Readme.md +++ b/Readme.md @@ -30,6 +30,7 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades ! ## Done +- hardcoded the levels unlock conditions so that they wouldn't change at each update - hide any tooltip on page scroll - added a "display level code" button in editor - passive income : paddle transparent for a much shorter time @@ -573,6 +574,7 @@ Here are a few interesting games in the breakout genre : - Wizorb : https://store.steampowered.com/app/207420/Wizorb/ - Ricochet infinity : https://www.myabandonware.com/game/ricochet-infinity-dxm - Whackerball : https://store.steampowered.com/app/2192170/Whackerball/ +- Arkanoid Archive lists many, many more https://www.youtube.com/@ArkanoidGame # PC game suggestions diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1f6906b..4a3c4d8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,8 +29,8 @@ android { applicationId = "me.lecaro.breakout" minSdk = 21 targetSdk = 34 - versionCode = 29092809 - versionName = "29092809" + versionCode = 29095000 + versionName = "29095000" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true diff --git a/app/src/main/assets/index.html b/app/src/main/assets/index.html index 691f327..fe62ab8 100644 --- a/app/src/main/assets/index.html +++ b/app/src/main/assets/index.html @@ -1 +1 @@ -Breakout 71 \ No newline at end of file +Breakout 71 \ No newline at end of file diff --git a/dist/index.html b/dist/index.html index 1a8fb26..6bc8cdf 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1640,7 +1640,7 @@ module.exports = JSON.parse("{\"_\":\"\",\"B\":\"black\",\"W\":\"#FFFFFF\",\"g\" module.exports = JSON.parse('[{"name":"icon:addiction","size":9,"bricks":"__________________________t__WWWWW_tWWWrrttttr_WWWWW_tr_______t__________________","credit":""},{"name":"icon:asceticism","size":8,"bricks":"_tttttt__tt__tt_____W_______r______________r_________r_____WWW__","credit":""},{"name":"icon:ball_attract_ball","size":8,"bricks":"__b__b____b__b__bbW__Wbb________________bbW__Wbb__b__b____b__b__","credit":""},{"name":"icon:ball_attracts_coins","size":8,"bricks":"WWW_____WWW_y___WWW____y__y_y____y____y_____y_____y____y___y_y__","credit":""},{"name":"icon:ball_repulse_ball","size":8,"bricks":"Wbb__bbWb______bb______b________________b______bb______bWbb__bbW","credit":""},{"name":"icon:base_combo","size":7,"bricks":"________ttttt__tytyt__ttttt__tytyt__ttttt________","credit":""},{"name":"icon:bigger_explosions","size":8,"bricks":"__O__Oy___Oyy_____OyOy__OyyyByOO_OOBBBy___yyByO__yOOy_OO_OO_____","credit":""},{"name":"icon:bigger_puck","size":8,"bricks":"_________GGGGGG__GGGGGG______________________W___________WWWWWW_","credit":""},{"name":"icon:bricks_attract_ball","size":8,"bricks":"ttW_____tt_y________y________ytt____y_tt___y____tty_____tt_y____","credit":""},{"name":"icon:bricks_attract_coins","size":9,"bricks":"______________________________bbbybbbbybbb______bbbybb___y_y______b_b______b_b___","credit":""},{"name":"icon:buoy","size":7,"bricks":"___y______y_____yyy__tyyyyytttOOOtttttOtttttttttt","credit":""},{"name":"icon:checkmark_checked","size":6,"bricks":"_ggggbgBBBbbbbBbbggbbbBggBbBBg_gggg_","credit":""},{"name":"icon:checkmark_unchecked","size":6,"bricks":"_gggg_gBBBBggBBBBggBBBBggBBBBg_gggg_","credit":""},{"name":"icon:clairvoyant","size":9,"bricks":"__y___y__y__y_y__y_y__t__y____ttt_____tWWWt___tWWgWWt_tttWWWttt__________________","credit":""},{"name":"icon:coin_magnet","size":8,"bricks":"__y__y_yy_________y_y_y_y________y_y______________y______WWW____","credit":""},{"name":"icon:coins","size":8,"bricks":"__bbbb___bbggbb_bbggggbbbggggggbbggggggbbbggggbb_bbggbb___bbbb__","credit":""},{"name":"icon:compound_interest","size":8,"bricks":"_________tttttt__ttt__t_____W________________r___________WWW__r_","credit":""},{"name":"icon:concave_puck","size":7,"bricks":"___W_____________W__________G__W__GGG___GGGGGGGGG","credit":""},{"name":"icon:corner_shot","size":9,"bricks":"___W________W________W__WW____W__WW____W________W______W_W_WWW_WW_W_WWWWWW_W_WWWW","credit":""},{"name":"icon:creative","size":7,"bricks":"bbg_bgg_______bbb_bgg_______bgg_bbg_______bbg_bbb","credit":""},{"name":"icon:double_or_nothing","size":10,"bricks":"_______________________yyyy____yyyyyyyy__yyyyyyyb_yyyyyyybbbyyyyyybbbb______________________________","credit":""},{"name":"icon:download","size":8,"bricks":"___bb______bb______bb______bb______bb____bbbbbb___bbbb__gggbbggg","credit":""},{"name":"icon:editor","size":10,"bricks":"_______ggg______gggg_____ggggg____ggggg____ggggg____ggggg____ggggg____bgggg_____bbgg______bbb_______","credit":""},{"name":"icon:etherealcoins","size":11,"bricks":"_____y_________yyy________bbb________bbb_______ybbby_____yybbbyy____yybbbyy____yybbbyy____y__y__y________________________","credit":""},{"name":"icon:extra_levels","size":6,"bricks":"__________t__W_tt_WWW_t__W_ttt______","credit":""},{"name":"icon:extra_life","size":9,"bricks":"___________GG_WG___GGWWGGW_GGWWGGWWGGWWGGWWGG_WGGWWGG___GWWGG_____WGG_______G____","credit":""},{"name":"icon:forgiving","size":8,"bricks":"____y______y_y____y___y__y_____yy_____y__y___y____y_y____WWWWW__","credit":""},{"name":"icon:fountain_toss","size":12,"bricks":"_____________________y_________y______________y______y__y_____WWWWWWWW___WttttttttW_WtytttytyttWWtttyttttttWWWtyttttytWW_WWWWWWWWWW___WWWWWWWWW_","credit":""},{"name":"icon:ghost_coins","size":7,"bricks":"__bbb___bbbbb_bbybybbbbbbbbbbbyyybbbbbbbbbbb_b_bb","credit":""},{"name":"icon:happy_family","size":9,"bricks":"__tt_tt____tt_tt____tt_tt____________________W_______W__W_W_W___________rrrWWWrrr","credit":""},{"name":"icon:helium","size":8,"bricks":"_y____y_yb____bybb___ybbb____b_b_____b____________________WWW___","credit":""},{"name":"icon:help","size":8,"bricks":"___bb_____bbbb___bb__bb__bb__bb_____bb_____bb______________bb___","credit":""},{"name":"icon:history","size":8,"bricks":"__gggg___ggbggg_gggbgggggggbggggggggbbgggggggggg_gggggg___gggg__","credit":""},{"name":"icon:hot_start","size":7,"bricks":"tt__ttt__t_trt_t__tttt_____ttttWttt________WWW___","credit":""},{"name":"icon:golden_goose","size":8,"bricks":"_bbby____bbb_y___bbby_y__y_y_y_y__y_y_y____y_y_y____y_y______y_y","credit":""},{"name":"icon:implosions","size":8,"bricks":"y______b___yb_b__y_Bbb_____Bbbby_bbbB_____bbB___yb_by___b_____y_","credit":""},{"name":"icon:left_is_lava","size":8,"bricks":"r_______rtttttt_rtttttt_r_______r_______r____W__r_______r_WWW___","credit":""},{"name":"icon:limitless","size":12,"bricks":"_________________________bbb____yyb_bbbbb__yyybbbb_bbbyyy_bbbb__bbby__bbbb_yybbb__bbyyyyyybbbbbb_yyy___bbbb_____________________________________","credit":""},{"name":"icon:metamorphosis","size":8,"bricks":"yyyyyy__yyyy__________W___________bbyybb__bbbbbb_________WWW____","credit":""},{"name":"icon:minefield","size":7,"bricks":"tB___Bttt___tt__ByB____yyy__tB___Bttt___tt_______","credit":""},{"name":"icon:multiball","size":8,"bricks":"_________tttttt__tttttt___________W__W____________________WWW___","credit":""},{"name":"icon:nbricks","size":7,"bricks":"________tttrt__ttr_r____________W__________WWW___","credit":""},{"name":"icon:new_run","size":7,"bricks":"_ggg____gbgg___gbbgg__gbbbg__gbbgg__gbgg___ggg___","credit":""},{"name":"icon:one_more_choice","size":7,"bricks":"WWW____WGGG___WGWWW__WGWGGG__GWGGG___WGGG____GGG_","credit":""},{"name":"icon:ottawa_treaty","size":8,"bricks":"BBbyybBBBbbyybbBbyybbbybbbyyyybbbbbyybbbbbyyybbbByybybbBBBbbbyBB","credit":""},{"name":"icon:passive_income","size":8,"bricks":"_ttttt___ttt_t________________W_____________________WWW_______r_","credit":""},{"name":"icon:picky_eater","size":8,"bricks":"_rrr_______rt_____rtt_____r_t______ttt_______W____________WWWW__","credit":""},{"name":"icon:pierce","size":6,"bricks":"ttttttttttWtttt__ttt__ttt__ttt__tttt","credit":""},{"name":"icon:pierce_color","size":8,"bricks":"tt___tttt__t_ttt_____ttt____ttttt____ttttt____ttttt____ttttt____","credit":""},{"name":"icon:premium","size":11,"bricks":"__g____g___g____g____g_g__gbg__g______g______gg_gbg_gg_gbbgbbbgbbggbbgbbbgbbg_gbgbbbgbg___ggggggg____ggggggg_____________","credit":""},{"name":"icon:puck_repulse_ball","size":8,"bricks":"__________________W_______b___W___b__b______b____________WWW____","credit":""},{"name":"icon:rainbow","size":10,"bricks":"yyyyybbb__yyyybbb___yyybbbr___yybbbOrr__ybbbyOOrr_bbbCyyOOrrbbtCCyyOOrb_ttCCyyOO___ttCCyyO____ttCCyy","credit":""},{"name":"icon:reach","size":8,"bricks":"tttttttttttttttttt____ttrr____rr___________W_____________WWW____","credit":""},{"name":"icon:reroll","size":8,"bricks":"__llllll_llBlBlelllllleBWWWWWeeeWBWBWeBeWWWWWeeeWBWBWBe_WWWWWe__","credit":""},{"name":"icon:reset","size":8,"bricks":"bb____bbbbb__bbb_bbbbbb___bbbb____bbbb___bbbbbb_bbb__bbbbb____bb","credit":""},{"name":"icon:respawn","size":9,"bricks":"tttttytttttttyyytttttttyttt_____________________________W_________________WWW____","credit":""},{"name":"icon:right_is_lava","size":8,"bricks":"_______r_ttttttr_ttttttr_______r_______r_____W_r_______r__WWW__r","credit":""},{"name":"icon:sacrifice","size":9,"bricks":"__b___b___bbb_bbb_bbyyyyybbbbybybybbbbyybyybb_bbyyybb___bybyb_____bbb_______b____","credit":""},{"name":"icon:sapper","size":9,"bricks":"_____WW______W__W_tttWttt_yttgggtt__tgggggt__tgggggt__tgggggt__ttgggtt__ttttttt__","credit":""},{"name":"icon:settings","size":9,"bricks":"___g_g____g_ggg_g___ggbgg__gggbbbggg_gbb_bbg_gggbbbggg__ggbgg___g_ggg_g____g_g___","credit":""},{"name":"icon:shocks","size":8,"bricks":"____y_Oy_bbbO_y__bbbOO_O_bbby_yyyyOyyOO_OO_ybbb__yO_bbb_y__ybbb_","credit":""},{"name":"icon:shunt","size":8,"bricks":"_______y______yy______yy__yttyyy__y__yyy_yy__yyy_yy__yyyyyy__yyy","credit":""},{"name":"icon:side_flip","size":7,"bricks":"________rtttt__rtttt____________W__________WWW___","credit":""},{"name":"icon:side_kick","size":7,"bricks":"________ttttr__ttttr__________W______________WWW_","credit":""},{"name":"icon:skip_last","size":5,"bricks":"_GGG_G_G_GGG_GGG_G_G_GGG_","credit":""},{"name":"icon:slow_down","size":10,"bricks":"_____________kk_______kkkk_____kkkkkkGG__kkkkkkGBG_kkkkkkGGGGkkkkkkGG__GGGGGG____GG__GG_____________","credit":""},{"name":"icon:smaller_puck","size":8,"bricks":"_________tttttt__tttttt_____________W_____________________yy____","credit":""},{"name":"icon:soft_reset","size":9,"bricks":"__yy______yyy_tt__yyyy_ttt_yyyy_tttt_____tttt_tttttttt_tttttttt__tttttt____tttt__","credit":""},{"name":"icon:starting_perks","size":8,"bricks":"_________b_b_b___________g_g_g_g_________g_g_g_g_________g_g_g_g","credit":""},{"name":"icon:sticky_coins","size":8,"bricks":"__________yy_yy___bbbby__ybbbb___ybbbb____bbbby______yy_________","credit":""},{"name":"icon:streak_shots","size":8,"bricks":"_tttttt__ttWttt___W_W____W___W__W_____W__W___W____W_W_____rrr___","credit":""},{"name":"icon:sturdy_bricks","size":7,"bricks":"tttttttttttttt____y_____y_y___y___y_______WWW____","credit":""},{"name":"icon:superhot","size":11,"bricks":"____________________________________________W_W_WWW_WWWWWW_W_W__W_W_W_WWW__W_____________________________________________","credit":""},{"name":"icon:telekinesis","size":8,"bricks":"______WW____GGWW___G______G_______G_______G_______G_____WWWWW___","credit":""},{"name":"icon:three_cushion","size":7,"bricks":"tttttttttttttt____r______r______r______r_____WWW_","credit":""},{"name":"icon:top_is_lava","size":8,"bricks":"rrrrrrrr_tttttt__tttttt____________________W_______________WWW__","credit":""},{"name":"icon:trampoline","size":8,"bricks":"_r_r_r_rrtttttt__ttttttrr___________W__rr______________r__WWW___","credit":""},{"name":"icon:transparency","size":9,"bricks":"__t_y_t___________t_y_t_y_t_________y_t_y_t_y_________t_y_t_y_t___________t_y_t__","credit":""},{"name":"icon:trickledown","size":8,"bricks":"_ybbbbbb_________y_y_y__bbbbbb____________y_y_y___bbbbbb_y______","credit":""},{"name":"icon:unbounded","size":8,"bricks":"bbyyyybbbbyyyybbbb____bbbb____bbbb____bbbb__y_bbbb____bbbbyyy_bb","credit":""},{"name":"icon:unlocked_levels","size":9,"bricks":"ggggggggggbbbgbbbggbgggggbggbgbgbgbgggggggggggbgbgbgbggbgggggbggbbbgbbbgggggggggg","credit":""},{"name":"icon:unlocked_upgrades","size":9,"bricks":"___ggg_____ggbgg___ggbbbgg_ggbbgbbgggbbbgbbbggggbgbggg__gbgbg____gbgbg____ggggg__","credit":""},{"name":"icon:upload","size":8,"bricks":"gggbbggg__bbbb___bbbbbb____bb______bb______bb______bb______bb___","credit":""},{"name":"icon:viscosity","size":8,"bricks":"________bb______ttbb__bbttttbbtttbttbtttttbttbtttttyttyttttttttt","credit":""},{"name":"icon:wind","size":9,"bricks":"_bb______b___yyyy_b_________bbbbbbb___________bbbbbbb_b________b___yyyy__bb______","credit":""},{"name":"icon:wrap_left","size":7,"bricks":"__W_______b_______b_______b_y_____y_b______WWW___","credit":""},{"name":"icon:wrap_right","size":7,"bricks":"___W_____b_____b_____y_____y_____b_____b____WWW__","credit":""},{"name":"icon:yoyo","size":8,"bricks":"____W____GGWGGG_GGWGGGGGGWGGGGGG_WWWWWW_GGGGGGGGGGGGGGGG_GGGGGG_","credit":""},{"name":"icon:zen","size":12,"bricks":"________________tttt_______tttttt_______tttt________BrrB_______tttttt_____tttttttt_____tttttt______BrrrrB_____tttttttt___tttttttttt___tttttttt__","credit":""},{"name":"71 mini","size":5,"bricks":"bbb____bt__btt__b_t___ttt","credit":""},{"name":"Butterfly","size":9,"bricks":"_________bb_t_t_bbbbb_t_bbbbbbbtbbbb_bbbtbbb____btb____bbbtbbb__bb_t_bb__________","credit":""},{"name":"Castle","size":7,"bricks":"s_s_s_ssssssssssBBBssssBBBssttbbbttttbbbtttbtbtbt","credit":""},{"name":"Eyes","size":9,"bricks":"ttttttt__tWWWWWWW_tWrrWttW_tWWWWWWW_ttttttt_____t______ttttt____ttttt_____t_t____","credit":"My favorite character in https://nuclearthrone.com/"},{"name":"Creeper","size":10,"bricks":"___________ccGGccGG__cGccGcGc__GBBccBBc__cBBGcBBc__GccBBGGc__ccBBBBcG__GGBBBBcG__cGBccBGc___________","credit":"https://en.wikipedia.org/wiki/Creeper_(Minecraft)"},{"name":"Stairs","size":8,"bricks":"tt______tt______bbtt____bbtt____vvbbtt__vvbbtt__ppvvbbttppvvbbtt","credit":""},{"name":"Dots","size":9,"bricks":"b_t_a_c_c__________b_t_a_c__________P_b_t_a_c__________P_b_t_a__________P_P_b_t_a","credit":""},{"name":"Lines","size":9,"bricks":"aaaaaaaa___________tttttttt_________aaaaaaaa___________tttttttt_________aaaaaaaa_","credit":""},{"name":"Heart","size":15,"bricks":"__________________RRR___RRR_____RSSSR_RSSSR___RSWWSSRSSSSSR__RSWSSSSSSSSSR__RSSSSSSSSSSSR__RSWSSSSSSSSSR___RSSSSSSSSSR_____RSSSSSSSR_______RSSSSSR_________RSSSR___________RSR_____________R_____________________________________","credit":"https://www.youtube.com/watch?v=gdWiTfzXb1g"},{"name":"Swiss","size":7,"bricks":"________RRRRR__RRWRR__RWWWR__RRWRR__RRRRR________","credit":""},{"name":"Germany","size":4,"bricks":"____ggggrrrryyyy","credit":""},{"name":"France","size":6,"bricks":"______ttWWrrttWWrrttWWrrttWWrrttWWrr","credit":""},{"name":"Smiley","size":8,"bricks":"_________yy__yy__yy__yy__________________yyyyyy___yyyy__________","credit":""},{"name":"Labyrinthe","size":11,"bricks":"_______tttS_Stttt_S________t___S__Stt_ttttt____t_____S__ttt_S_S____t___t_tttt_t_S_t____tSt_t_t_Sttt___t_t_____Sttt_tttttS","credit":""},{"name":"Temple","size":11,"bricks":"_______________WWW______WWWWWWW___WWWWWWWWW___b_b_b_b____b_b_b_b____v_v_v_v____P_P_P_P____P_P_P_P____WWWWWWW___WWWWWWWWW_","credit":""},{"name":"Pacman","size":12,"bricks":"____yyyy______yyyyyyyy___yyyyByyyyy__yyyyyyyyy__yyyyyyyy____yyyyyy______yyyyyy___S_Syyyyyyyy_____yyyyyyyyy___yyyyyyyyyy___yyyyyyyy______yyyy____","credit":"https://en.wikipedia.org/wiki/Pacman"},{"name":"Ship","size":11,"bricks":"____sWW________sWWW_______sWWW_______s___OOOOOOOOOOOOOO_OBOBOBOBOO__OOOOOOOO_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb___________","credit":""},{"name":"We come in peace","size":13,"bricks":"________________a_____a_______a___a_______aaaaaaa_____aaBaaaBaa___aaaaaaaaaaa__aaaaaaaaaaa__a_aaaaaaa_a__a_a_____a_a_____aa_aa___________________________________________","credit":"https://en.wikipedia.org/wiki/Space_invaders"},{"name":"Space mushroom","size":10,"bricks":"______________WW_______WWWW_____WWWWWW___WWBWWBWW__WWWWWWWW____W__W_____W_WW_W___W_W__W_W___________","credit":"https://en.wikipedia.org/wiki/Space_invaders"},{"name":"Wololo","size":9,"bricks":"____WW_OOW___WW__OWW__W___OWWWbbbW_WWW_WbW_WOW__WWb__OW__bbb__O___W_W__O___W_W__O","credit":"https://aoe.heavengames.com/theacademy/unitsboatsandbuildings/priest/"},{"name":"Small heart","size":15,"bricks":"________________________________RRRR___RRRR___RrWWrR_RWWrrR__RWWrrrRWWrrrR__RrrrrrrrrrrrR__RrrrrrrrrrrrR___RrrrrrrrrrR_____RrrrrrrrR_______RrrrrrR_________RrrrR___________RrR_____________R_____________________________________","credit":""},{"name":"Eye","size":9,"bricks":"____________ggg_____gWWWg___gWbbbWg_gWWbBbWWg_gWbbbWg___gWWWg_____ggg____________","credit":""},{"name":"Enderman","size":10,"bricks":"___________gggggggg__gggggggg__gggggggg__gggggggg__vvvggvvv__gggggggg__gggggggg__gggggggg___________","credit":"https://minecraft.wiki/w/Enderman"},{"name":"Mushroom","size":16,"bricks":"_____________________rrrrWW________WWrrrrWWWW_____WWrrrrrrWWWW____WrrWWWWrrWWW___rrrWWWWWWrrrrr__rrrWWWWWWrrWWr__WrrWWWWWWrWWWW__WWrrWWWWrrWWWW__WWrrrrrrrrrWWr__WrrWWWWWWWWrrr_____WWBWWBWW_______WWWBWWBWWW______WWWWWWWWWW_______WWWWWWWW____________________","credit":"https://pixelartmaker.com/art/cce4295a92035ea"},{"name":"Tulip","size":11,"bricks":"______________R_R_R______RRRRR______RRRRR______RRRRR_______RRR_________k________k_k_k______k_k_k_______kkk_________k_____","credit":""},{"name":"Chain","size":7,"bricks":"yyy____yBy____yyyyy____yBy____yyyyy____yBy____yyy","credit":""},{"name":"Marion","size":9,"bricks":"rr_____rr_rr___rr__rrr_rrr__rrrrrrr__rr_r_rr__rr___rr__rr___rr__rr___rr_rrr___rrr","credit":""},{"name":"Renan","size":9,"bricks":"yyyyyyy___yyyyyyy__yy___yy__yy___yy__yyyyyy___yy_yy____yy__yy___yy___yy_yyy___yyy","credit":""},{"name":"Violet Pairs","size":8,"bricks":"b_b_b_b_b_b_b_b__________t_t_t_t_t_t_t_t________b_b_b_b_b_b_b_b_","credit":""},{"name":"Red Cups","size":11,"bricks":"___________rBr_rBr_rBrrrr_rrr_rrr___________r_rBr_rBr_rr_rrr_rrr_r___________rBr_rBr_rBrrrr_rrr_rrr______________________","credit":""},{"name":"Cactus","size":10,"bricks":"____G______rG_Gk______G_Gk______kkkk_r_____kkk_G______GkGk_____rGkk_______Gk________kk________kk____","credit":""},{"name":"Sunny Face","size":11,"bricks":"____yyy______yyyyyyy___yyyyyyyyy__yyyyyyyyy_yyyWWyWWyyyyyyyyyyyyyyyyyyyyyyyyy_yyWWWWWyy__yyyWWWyyy___yyyyyyy______yyy____","credit":""},{"name":"Mountain","size":9,"bricks":"_______________W_______WWW______GGWW__W_GGGGG_kkkGGGGG_kkkkGGGGkkkkkGGGGkkkkkkGGG","credit":""},{"name":"Dollar","size":17,"bricks":"________________________G_G______________G_G____________GGGGGGG_________GGGGGGGGG_______GG__G_G__GG______GG__G_G__GG______GG__G_G___________GGGGGGGG__________GGGGGGGG___________G_G__GG______GG__G_G__GG______GG__G_G__GG_______GGGGGGGGG_________GGGGGGG____________G_G______________G_G_______","credit":""},{"name":"Waves","size":8,"bricks":"___bbb____bbb____bbttbbbbbttbbbbttttaatttttaattttaaaaaaa________","credit":""},{"name":"Box","size":8,"bricks":"yyyyyyyyy______yy_bbbb_yy_b__b_yy_b__b_yy_bbbb_yy______yyyyyyyyy","credit":""},{"name":"Rose","size":9,"bricks":"__SS______SSSS_____SSSS_____SSSS______SS_k______k_kk_____kk_k______kk________k___","credit":""},{"name":"Time","size":9,"bricks":"__________WWWWWWW___WWWWW_____yyy_______y________y_______WyW_____WyyyW___yyyyyyy_","credit":""},{"name":"Watermelon","size":8,"bricks":"_____Sk_____SSBk___SBSSk__SSSSSk_SSBSSk_SBSSSSk_kSSSkk___kkk____","credit":""},{"name":"Worms","size":13,"bricks":"___sssss_______sssssss______WWsWWsss_____WBsBWsss_____WBsBWsss_____WWsWWsss_____sssssss_______ssssss_____WWWWWWss_______WssWs__s_____ssss__sss___sssssssssss__sssssssss_s","credit":"https://en.wikipedia.org/wiki/Worms_(series)"},{"name":"Ocean Sunrise","size":8,"bricks":"SSSSSSSSSSSyySSSSSyyyySSSyyyyyySbttttttbbbttttbbbbbttbbbbbbbbbbb","credit":""},{"name":"Crosses","size":13,"bricks":"b___b___b___b__v___v___v___vvv_vvv_vvv___v___v___v__p___p___p___ppp_ppp_ppp_ppp___p___p___p__P___P___P___PPP_PPP_PPP___P___P___P__p___p___p___ppp_ppp_ppp_ppp___p___p___p","credit":""},{"name":"Negative space","size":9,"bricks":"tttttttttt_t_t_t_t_________b_b_b_b_bbbbbbbbbb_b_b_b_b___________t_t_t_t_ttttttttt","credit":""},{"name":"UK","size":11,"bricks":"brbbWrWbbrbbbrbWrWbrbbbbbrWrWrbbbWWWWWrWWWWWrrrrrrrrrrrWWWWWrWWWWWbbbrWrWrbbbbbrbWrWbrbbbrbbWrWbbrb______________________","credit":""},{"name":"Greece","size":11,"bricks":"ttWttttttttttWttWWWWWWWWWWWttttttttWttWWWWWWttWttttttttWWWWWWWWWWWtttttttttttWWWWWWWWWWWttttttttttt______________________","credit":""},{"name":"Russia","size":8,"bricks":"________WWWWWWWWWWWWWWWWttttttttttttttttrrrrrrrrrrrrrrrr________","credit":""},{"name":"Ukraine","size":8,"bricks":"________ttttttttttttttttttttttttyyyyyyyyyyyyyyyyyyyyyyyy________","credit":""},{"name":"Poland","size":7,"bricks":"________WWWWW__WWWWW__rrrrr__rrrrr_______________","credit":""},{"name":"Yellow 71","size":9,"bricks":"_________yyyyy__yyyyyyy_yyy___yy__yy__yyy__yy_yyy___yy_yy____yy_yy____yy_________","credit":""},{"name":"71 on white","size":6,"bricks":"WWWWWWrrrWWrWWrWrrWrWWWrWrWWWrWWWWWW","credit":""},{"name":"Blue 71","size":8,"bricks":"ttttt__bttttt_bb___ttbbb__tt__bb__tt__bb_tt___bb_tt___bb_tt___bb","credit":""},{"name":"Seventy one","size":21,"bricks":"rr_yy_rrry_yrrry_yrrrr_ry_yr__y_yr_ry_y_r_rr_yy_rr_yy_r_ry_y_r_r_ry_yr__y_yr_ry_y_r_rr_y_yrrry_yrrryyy_r_yyy__________________y______________r_____yyyrrry_yrrryyyrr_y_y__yrr_y_yrr_y_yr__y_yyyyrrr_y_rrry_yrrryyy____________________yrrryyyrrr_________yy_r_ry_yrr_____________rrry_yrrryyyyyyyyyyyy___________________________________________________________________________________________________________________________________________________","credit":""},{"name":"B71","size":10,"bricks":"__________bbbtttt_b_b__b__tbb_b__b__t_b_bbb__t__b_b__b_t__b_b__bt___b_bbb_t__bbb____________________","credit":""},{"name":"Pig","size":9,"bricks":"__________PP___PP__PPP_PPP__WWPPPWW__WBPPPBW__PPsssPP__PsBsBsP__PPsssPP__________","credit":""},{"name":"Big Pig","size":15,"bricks":"________________sss_______sss__ss__sssss__ss____sssssssss_____sWBsssssBWs___ssBBsssssBBss__ssss_____ssss__sss_sssss_sss__sss_sBsBs_sss__sss_sssss_sss___sss_____sss____sssssssssss__GGGsssssssssGGGGGGsGsssssGsGGGGGGssGGGGGssGGG","credit":""},{"name":"Donkey Kong","size":9,"bricks":"OOr__a___OOr__a___ppppppp_O______a________a____pppppppr_a______b_a___O__ppppppp__","credit":""},{"name":"Banana","size":12,"bricks":"_________________e__________eee_________eee_________eee_________eeeyy_____yyeeyyyy___yyyyey_yC___yy_yyy___C_____yyyy_________yyyy_________yyyy__","credit":""},{"name":"Fox","size":8,"bricks":"e______eee_OO_eeeeOOOOeeeOBOOBOeOOOOOOOO_WWBBWW___WWWW_____WW___","credit":""},{"name":"Wiki","size":10,"bricks":"_______________________GGGG_____GGkkGG___GkggggkG__GgWWWWgG__GkggggkG___GGkkGG_____GGGG_____________","credit":""},{"name":"Baby Dog","size":8,"bricks":"_______W__eeeeWWWWeeWeWWWeBWeBeeeeWWWWee_eWBBWe__eWWWWe____WW___","credit":""},{"name":"dog 21","size":9,"bricks":"__________O_____O_OOOWWWOOOOOWWWWWOOOOeWWWWOO_eBeWWBW__eBeWWBW___eWBWW_____WRW___","credit":"https://prohama.com/dog-21-pattern/"},{"name":"A","size":7,"bricks":"__ttt___ttttt_ttt_ttttt___ttttttttttt___tttt___tt","credit":""},{"name":"B","size":9,"bricks":"_bbbbb_____bb_bb____bb_bb____bb_bb____bbbb_____bb_bb____bb_bb____bb_bb___bbbbb___","credit":""},{"name":"C","size":8,"bricks":"__rrrr___rrrrrr_rrr___rrrr______rr______rrr___rr_rrrrrr___rrrr__","credit":""},{"name":"D","size":8,"bricks":"_GGGGG____GG__G___GG__GG__GG__GG__GG__GG__GG__GG__GG__G__GGGGG__","credit":""},{"name":"e","size":8,"bricks":"__tttt___tttttt_tt____tttt____tttttttttttt_______tt__tt___tttt__","credit":""},{"name":"Elephant","size":18,"bricks":"_________________________llll_________lll_llllll_lll___lsssllllllllsssl__lsssllllllllsssl__lsssllBllBllsssl__lssllWllllWllssl___ll__llllll__ll_________llll_______________ll______________llll______________ll______________________________________________________________________________________________________________________","credit":"https://prohama.com/elephant-5-pattern/"},{"name":"Orca","size":20,"bricks":"____________________________________________________________________________________________ggggg____ggg_ggg___ggggggg____ggggg___ggggggggg____ggg___ggggWggWWW_____gggggggggggWWWW_____ggggggggggWWWWW_____gggggggggWWWWW_______gggggggWWWWW___________WWggWWW______________ggg_gg______________gg__g__________________________________________________________________________________________________________","credit":"https://prohama.com/whale-2-pattern/"},{"name":"Shark","size":17,"bricks":"__________________________________________g_______________ggg____________ggggggg_________ggggggggg_______ggggggggggg_____gggggWWWggggg____gBgWWWWWWWgBg___ggWWWWrWrWWWWgg__ggWWWrrrrrWWWgg_ggWWWrrrrrrrWWWggggWWrrrrrrrrrWWgggWWWrWrWrWrWrWWWggWWrrWWWWWWWrrWWggWWWWWWWWWWWWWWWg_________________","credit":"https://prohama.com/shark-2-pattern/"},{"name":"Bird","size":13,"bricks":"_______RRR____R____RSSSR___RR__RSSWWWR__RSR_RSWWBWR__RSSRRSWWWWyy_RSSSRSWWWR___RSSSSSSRR_____RRSSyyyy______RSyyyyy___RRRRSyyyy____RSSSRyyy_____RRRR______________________","credit":"https://prohama.com/bird-1-size-13x12/"},{"name":"Tux","size":14,"bricks":"_____gggg________gggggggg_____gggggggggg____gggggggggg___gggggggggggg__gggWBggWBggg__gggBBggBBggg__ggggyyyygggg_ggggggyyggggggggggWWWWWWggggg_gWWWWWWWWg_g__WWWWWWWWWW____WWWWWWWWWW____yyy____yyy__","credit":"https://prohama.com/pingwin-4-pattern/"},{"name":"Armenia","size":6,"bricks":"_______rrrr__bbbb__yyyy_____________","credit":""},{"name":"Austria","size":6,"bricks":"_______rrrr__WWWW__rrrr_____________","credit":""},{"name":"Benin","size":8,"bricks":"_________kkyyyy__kkyyyy__kkrrrr__kkrrrr_________________________","credit":""},{"name":"Botswana","size":10,"bricks":"___________tttttttt__tttttttt__tttttttt__WWWWWWWW__BBBBBBBB__WWWWWWWW__tttttttt__tttttttt__tttttttt_","credit":""},{"name":"Bulgaria","size":6,"bricks":"_______WWWW__cccc__rrrr_____________","credit":""},{"name":"Canada","size":7,"bricks":"________rWWWr__rWrWr__rWWWr______________________","credit":""},{"name":"Chad","size":8,"bricks":"_________bbyyRR__bbyyRR__bbyyRR_________________________________","credit":""},{"name":"China","size":6,"bricks":"______RRyRRRRyRyRRRRyRRRRRRRRR______","credit":""},{"name":"Colombia","size":7,"bricks":"________yyyyy__yyyyy__bbbbb__RRRRR_______________","credit":""},{"name":"Republic of the Congo","size":7,"bricks":"________kkkyy__kkyyr__kyyrr__yyrrr_______________","credit":""},{"name":"C\xf4te d\'Ivoire","size":8,"bricks":"_________OOWWGG__OOWWGG__OOWWGG_________________________________","credit":""},{"name":"Denmark","size":8,"bricks":"_________rrWrrr__rrWrrr__WWWWWW__rrWrrr__rrWrrr_________________","credit":""},{"name":"El Salvador","size":8,"bricks":"_________bbbbbb__bbbbbb__WWWkWW__WWkWWW__bbbbbb__bbbbbb_________","credit":""},{"name":"Egypt","size":8,"bricks":"_________RRRRRR__RRRRRR__WWWyWW__WWyWWW__gggggg__gggggg_________","credit":""},{"name":"Estonia","size":8,"bricks":"_________tttttt__tttttt__gggggg__gggggg__WWWWWW__WWWWWW_________","credit":""},{"name":"Finland","size":6,"bricks":"_______WtWW__tttt__WtWW_____________","credit":""},{"name":"Gabon","size":5,"bricks":"______CCC__yyy__ttt______","credit":""},{"name":"Georgia","size":9,"bricks":"__________WrWrWrW__WWWrWWW__rrrrrrr__WWWrWWW__WrWrWrW____________________________","credit":""},{"name":"Guinea","size":8,"bricks":"_________rryycc__rryycc__rryycc_________________________________","credit":""},{"name":"Indonesia","size":6,"bricks":"_______rrrr__rrrr__WWWW__WWWW_______","credit":""},{"name":"Pingwin","size":13,"bricks":"______gggg________ggWWgg_______gWWgWgy______ggWWWg_______ggggg_______gggWWW______gggggWWW___gggggggWWW____ggggggWWW_____ggggWWWW____gggWWWWW______ggWWWW________gWWyyy___","credit":"https://prohama.com/pingwin-2-pattern/"},{"name":"Dog 8","size":17,"bricks":"_____________________________________gg_ggggg_gg____ggWWgWWWWWgWWgg__gWWgWWWWWWWgWWg__gWWgWWWWWWWgWWg__gggWWWWWWWWWggg___gWggWWWWWggWg____gWggWWWWWggWg____gWWWWgggWWWWg_____gWgWWgWWgWg______gWWggsggWWg_______gWgsssgWg_________ggsssgg____________ggg_________________________________________","credit":"https://prohama.com/dog-8-pattern/"},{"name":"Sunglasses","size":24,"bricks":"____________________________________________________ggggg______ggggg_______gg___g______g___gg_____gg________________gg___gg__________________gg_gggggggggg____gggggggggggggtttttggggggggbbbbbgggggtWWWttttggggbbbbWWWbgg_gtWttttttggggbbbbWbbbg__gtttttttgg__ggbbbbbbbg__gtttttttg____gbbbbbbbg__ggtttttgg____ggbbbbbgg___ggtttgg______ggbbbgg_____ggggg________ggggg___________________________________________________________________________________________________________________________________________________________________________________________________________________________","credit":"https://prohama.com/sunglasses-pattern-1/"},{"name":"Balloon","size":21,"bricks":"_____bbbWbbbWbbb_________PWbWPWbWPWbWP_______bWbbbWbbbWbbbWb_____WbbbWbbbWbbbWbbbW___WPWbWPWbWPWbWPWbWPW__bWbbbWbbbWbbbWbbbWb__bbbPbbbPbbbPbbbPbbb__bbPPPbPPPbPPPbPPPbb___PPWPPPWPPPWPPPWPP____PWbWPWbWPWbWPWbWP_____PWPPPWPPPWPPPWP_______PPWPPPWPPPWPP_________WbWPWbWPWbW___________bbbbbbbbb_____________b_____b______________b_____b______________b_____b______________WWWWWWW_______________PPPPP________________PPPPP________________PPPPP________","credit":"https://prohama.com/balloon-1/"},{"name":"Opening","size":14,"bricks":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbyyyyyyyyyyyybbyB___BB___Bybby__________ybbyyy______yyybbbbyyB__Byybbbbbbbyy__yybbbbbbbbby__ybbbbbyyyyby__ybyyyy___yby__yby______yby__yby______yBy__yBy______yyy__yyy___","credit":""},{"name":"Stripes","size":17,"bricks":"bbb______tttttt________tttttt________tttttt______bbtttttt______bbbbbttt______bbbbbb________bbbbbb________bbbbbb______ttbbbbbb______tttttbbb______tttttt________tttttt________tttttt______bbtttttt______bbbbbttt______bbbbbb________bbbbbb________bbbbbb________bbbbbb___________bbb______________","credit":""},{"name":"You are here","size":13,"bricks":"_____rrr_________rrrrr_______rrr_rrr______rr___rr______rr___rr_______rr_rr________rrrrr_________rrr__________rrr_________WWrWW_______WWWrWWW______WWWWWWW_______WWWWW____","credit":""},{"name":"Gear","size":13,"bricks":"_________________l_l_l______l_lllll_l_____lllllll____lllll_lllll___lll___lll___lll_____lll___lll___lll___lllll_lllll____lllllll_____l_lllll_l______l_l_l_________________","credit":""},{"name":"Play","size":15,"bricks":"_________________rrrrrrrrrrr___rrrrWWrrrrrrr__rrrrWWWrrrrrr__rrrrWWWWrrrrr__rrrrWWWWWrrrr__rrrrWWWWWWrrr__rrrrWWWWWrrrr__rrrrWWWWrrrrr__rrrrWWWrrrrrr__rrrrWWrrrrrrr___rrrrrrrrrrr_______________________________________________","credit":""},{"name":"City","size":18,"bricks":"_______yyy___bbbbb________yyy__ybyyb________yyy__ybyyb__tt___yyy_b_ybbbb_tttt______bbbbbbbtttttt_______ybyybbbbbbb_______ybyybbyybyb_____b_ybbbbbyybyb_____bbbbbbbbbbbbb__bb___bbbbbbybyyb_bbbb__ybyybbybyybbbbbbb_ybyybbbbbbbtttttt_ybbbbbyybybtyyyyt_bbbbbbyybybtyyyyt_bbbbbbbbbbbtttttt_byybybybyybtytyyt_byybybybyybtttttt_byybb","credit":""},{"name":"Wiggle","size":17,"bricks":"__________________cccccc_ccc_cccc__c____c_c_c_c__c__ccc_cc_c_ccc_cc____c_c__c_____c___ccc_cccc_ccc_cc__c________c_c__c__ccc_ccc_cc_cccc____c_c_c_c________ccc_c_c_ccccccc__c___c_________c__ccc_ccccccccccc____c______________ccc_ccc_ccc_ccc__c___c_c_c_c_c_c__ccccc_ccc_ccc_c__________________","credit":""},{"name":"Graph","size":18,"bricks":"_______________________yy________________yyt__yytttt______tt_tttyy___t____yyt____t_____t____yy____tt_____t____t_____t______yy___t_____t______yy__tt_____yytttttt___tt___ttyy_____t___t____t__t_____t___yytttt__t_____t___yy______tt____t____t_______yy___t____ttt_____yyttyy______tyy___t___yy_______yytttt_________________________","credit":""},{"name":"Lightbulb","size":14,"bricks":"_______________y__yyyyy___y____yyyyyyy______yyyyyyyyy_____yyyyyyyyy___y_yyyyyyyyy__y__yyyyyyyyy_____yyyyyyyyy_____yyyBBByyy___y__yyByByy___y____yByBy_________lllll______y___lll___y_______lll______","credit":""},{"name":"Note","size":16,"bricks":"_____________WWW__________WWWWWW_______WWWWWW__W____WWWWWW_____W____WWW________W____W__________W____W__________W____W__________W____W__________W____W________WWW____W_______WWWW____W_______WWW___WWW____________WWWW____________WWW____________________________","credit":""},{"name":"Rocket","size":13,"bricks":"______b___________bbb_________bbBbb________btttb________ttBtt________ttttt________ttBtt________ttttt________ttBtt_______bbtttbb_____bbbyyybbb____bbbyyybbb____bb_ByB_bb__","credit":""},{"name":"Abstract","size":16,"bricks":"________________aaaaa_cccc_aaaaaaaaaa_cccc_aaaaa________________aaaa_cccc_aaaaaaaaaa_cccc_aaaaaa________________aaa_cccc_aaaaaaaaaa_cccc_aaaaaaa________________aa_cccc_aaaaaaaaaa_cccc_aaaaaaaa________________a_cccc_aaaaaaaaaa_cccc_aaaaaaaaa________________","credit":""},{"name":"Fingerprint","size":15,"bricks":"___SSSSSSSS______S_______SS____S__SSSSS__SS__S__S____SS__S____S__SS__SS_S___S__S_SS__S__S_S__S___SS_SS__SS_S_____S___S__S_S__SS__S__SS_S_S_SS_S__S__S_S_S_S___S_S__S_S_S_S___S_S__S___S_S___S_S__S__S__S___S_S__S__S__S__S___S_S_","credit":""},{"name":"Leaf","size":14,"bricks":"____________________________________________________________GGkGG________GGkGGkGG_____GGkGGkGGkkG_kkkkkkkkkkkGGG__GGkGGkGGkkG____GGkGGkGG_______GGkGG_______________________________________________","credit":""},{"name":"Abstract 2","size":14,"bricks":"______________yyyy______yyyy______________bbb_bbbbbb_bbbbb___bbbb___bbb__y__bb__y__b______________bbb_bbbbbb_bbbbb___bbbb___bbb__y__bb__y__b______________bbb_bbbbbb_bbbbb___bbbb___bbb__y__bb__y__b","credit":""},{"name":"Abstract 3","size":13,"bricks":"______________p_aaa_ppp_a__p___a_p___a__ppp_a_p_aaa_______________aaa_p_a_ppp__a___p_a___p__a_ppp_aaa_p_______________p_aaa_ppp_a__p___a_p___a__ppp_a_p_aaa______________","credit":""},{"name":"Abstract 4","size":13,"bricks":"______________y_y_y_y_y_y__y_y_y_y_y_y__y_y_y_y_y_y_______________bbb_bbb_bbb_______________bbb_bbb_bbb_______________y_y_y_y_y_y__y_y_y_y_y_y__y_y_y_y_y_y______________","credit":""},{"name":"Abstract 5","size":13,"bricks":"______________ccc_ccc_ccc__c_a_c_c_a_c__caa_aaa_aac_______________cca_aaa_acc__c_a_a_a_a_c__cca_aaa_acc_______________caa_aaa_aac__c_a_c_c_a_c__ccc_ccc_ccc______________","credit":""},{"name":"Abstract 6","size":13,"bricks":"_vvvvv_vvvvv__v___v_v___v__v_bbbbbbb_v__v_b_v_v_b_v__v_b_v_v_b_v__v_b_v_v_b_v__v_b_v_v_b_v__v_b_v_v_b_v__v_b_v_v_b_v__v_b_vvv_b_v__v_b_____b_v__vvvvvvvvvvv_bbbb_____bbbb","credit":""},{"name":"Hemiola","size":11,"bricks":"___gggg_____gggrrgg_____ggrrg_______gggg_____gggyygg_____ggyyg_______gggg_____gggCCgg_____ggCCg_______gggg________gg_____","credit":"Left a wonderful review on the play store."},{"name":"Obigre","size":13,"bricks":"_______________________________________OOOORgRgRgOOOOWOORgRgRgOOOOOWORgRgRgOWOOWOORgRgRgOOWOOWORgRgRgOWOOWOORgRgRgOOOOOOORgRgRgOOO_______________________________________","credit":"Colin helped a lot with the game design https://colin-crapahute.bearblog.dev/"},{"name":"Noodlemire","size":15,"bricks":"_________________________________ggggggggg_____g_________g___g___________g_g_____________gg_____________gg_____yyy_____ggg__yyyyyyy__ggggtyyyyyyyyytggggtttttttttttgggg_ttttttttt_gg_____ttttt___________________________________","credit":"Early adopter of the game"},{"name":"Bearded axe","size":12,"bricks":"______________WyyyOOy_____WyyyOOy_____Wyy_OO______Wyy_OO______Wyy_OO__________OO__________OO__________OO__________OO__________OO__________OO____","credit":"Did some nice bug reports"},{"name":"Lebanon","size":9,"bricks":"_________rrrrrrrrrWWWWkWWWWWWWkkkWWWWWkkkkkWWWWWWkWWWWrrrrrrrrr__________________","credit":""},{"name":"Spain","size":9,"bricks":"_________rrrrrrrrryyyyyyyyyyWrWyyyyyyrWryyyyyyWrWyyyyyyyyyyyyyyrrrrrrrrr_________","credit":""},{"name":"Uzbekistan","size":8,"bricks":"tWtttWttWtttWttttWtWtWttWWWWWWWWWWWWWWWWGGGGGGGGGGGGGGGGGGGGGGGG","credit":""},{"name":"Pakistan","size":8,"bricks":"________WWkkkkkkWWkkWkWkWWkWkkkkWWkWkkWkWWkkWWkkWWkkkkkk________","credit":""},{"name":"Korea","size":10,"bricks":"__________WWWWWWWWWWWgWWWWWWgWWgWrrrrWgWWWWrrbbWWWWWWrrbbWWWWgWbbbbWgWWgWWWWWWgWWWWWWWWWWW__________","credit":""},{"name":"Chile","size":9,"bricks":"_________tttWWWWWWtWtWWWWWWtttWWWWWWrrrrrrrrrrrrrrrrrrrrrrrrrrr__________________","credit":""},{"name":"T\xfcrkiye","size":12,"bricks":"____________rrrrrrrrrrrrrrrWWWrrrrrrrrWWrrrrrrrrrWWrrWrWrrrrrWWrrrWrrrrrrWWrrWrWrrrrrrWWrrrrrrrrrrrWWWrrrrrrrrrrrrrrrrrr________________________","credit":""},{"name":"Taj Mahal","size":11,"bricks":"_____e________WWWWW_____WWWWWWW____WWWWWWW____WWWWWWW__W__lllll__WWWeeeeeeeWWeeeeeWeeeeeeleeWWWeeleeeeWWWWWeeeeleWWlWWele","credit":"An approximative reproduction "},{"name":"Abstract 7","size":9,"bricks":"__________SS_t_SS__S_____S____t_t____t_____t____t_t____S_____S__SS_t_SS__________","credit":""},{"name":"Abstract 9","size":8,"bricks":"PP_vv_PP_P__v__P________vv_PP_vvv__P__v_________PP_vv_PP_P__v__P","credit":""},{"name":"Crosshair","size":9,"bricks":"____W_____WWWWWWW__WB_W_BW__W_____W_WWW_B_WWW_W_____W__WB_W_BW__WWWWWWW_____W____","credit":""},{"name":"Abstract 10","size":15,"bricks":"bbbB_ttttt_BbbbbBbb_ttBtt_bbBbb____tt_tt____bbbbb_tt_tt_bbbb_______________ttttt_b_b_tttttt_____b_b_____tt_ttt_b_b_ttt_ttBtBt_bBb_tBtBtttt_t_bbb_t_ttt________________bb_ttttttt_bb__Bb_tB___Bt_bB__Bb_ttt_ttt_bB_bbb_________bbb","credit":""},{"name":"Face","size":6,"bricks":"SSSSSSSOOOOSSBOOBSSOOOOSSOOOOS_OSSO_","credit":""},{"name":"Eiffel tower","size":11,"bricks":"_____O__________O__________O__________O_________OOO________OOO____k___O_O___kkk_OO_OO_kkkkkOOOOOkkkkkOOO_OOOkkkOOO___OOOk","credit":""},{"name":"Abstract 11","size":9,"bricks":"P_t_s_t_PP_t___t_PP_ttttt_PP_______PPPPPPPPPPP_______PP_sssss_PP_s___s_PP_s_t_s_P","credit":""},{"name":"Abstract 12","size":8,"bricks":"BbBb____bbbb____BbBb____bbbb________tBtB____tttt____tBtB____tttt","credit":""},{"name":"Abstract 13","size":9,"bricks":"SSSSbSSSSSbbSbSbbSSbbS_SbbSSSSS_SSSSbb_____bbSSSS_SSSSSbbS_SbbSSbbSbSbbSSSSSbSSSS","credit":""},{"name":"Abstract 14","size":11,"bricks":"aa_tt_aa_ttaa_tt_aa_tt__B__B__B__bb_aa_bb_aabb_aa_bb_aa__B__B__B__aa_bb_tt_bbaa_bb_tt_bb__B__B__B__tt_aa_bb_aatt_aa_bb_aa","credit":""},{"name":"S","size":10,"bricks":"___________Oyyyyyyy__Oyyyyyyy__Oyy__Oyy__Oyy_______Oyyyyyyy_______Oyy__Oyy__Oyy__Oyyyyyyy__Oyyyyyyy_","credit":""},{"name":"Abstract 15","size":11,"bricks":"____________S_vvv_SSS__S___v___S__SSS_vvv_S__________S__S_vvv_SSS__S___v______SSS_vvv_S____S_____S__v_SSS_SSS____________","credit":"Just random strokes"},{"name":"Mario!","size":11,"bricks":"________________________RRRRR_____RRRRRRRRR__kkkOOkO___kOkOOOkOOO_kOkkOOOkOOOkkOOOOkkkk___OOOOOOO________________________","credit":"Suggested by Nicolas03. A Mario level ! Sprite taken from https://art.pixilart.com/sr2d5c0683c82aws3.png . The sprite belongs to Nintendo"},{"name":"Minesweeper","size":16,"bricks":"___llltCCttBC______lllCBBttCB______lttbBbtltt______ltBrBClttt______lttCCCttBt______llttCBtttt______ltCBCttlll______ltBCCtCtCt______lttCCBCBrB______llltBCCtrB______ttttttlltt______CBrttlllll______CBrBCttttl______ttCCBttBtl______tttCCCtCCt______tBttBtltBt___","credit":"Suggested by Noodlemire. For once, you\'ll want to trigger as many mines as possible."},{"name":"Target","size":19,"bricks":"__________________________________________________________________________________________________________________________WWW_______________WrrrW_____________WrWWWrW____________WrWBWrW____________WrWWWrW_____________WrrrW_______________WWW__________________________________________________________________________________________________________________________","credit":"Suggested by Noodlemire. Unusually small level, with lots of room to miss your shots. Acts as decent aim practice."},{"name":"The Boys","size":10,"bricks":"__________rrrrr_____WWrWWrrrrrWWrWWWWrWWWWrWWWWrWWrWrWWWWrWWWrWWWrWrWW_____WrWWW____________________","credit":"Suggested by Bearded-Axe. My boys initals"},{"name":"A Very Dangerous High-Five","size":21,"bricks":"__________________________________________________yy_______________yy__yy__yy___________yy__yy__yy____________yy__yy_yy_________y__yy__yy_yy________yyy_yyy_yy_yy_________yy__yy_yyyyy__________yy_yyyyyyyy___yyy____yyyyygggyyy__yyy______yyygBBBgyy_yyy________ygBBBBBgyyyy__W______ygBBBBBgyyy__________yygBBBgyyyy___________yygBgyyyy____________yyyByyyy_____________yyyyByy_______________yyByy_________________r_________________________________","credit":"Suggested by Noodlemire. A unique shape, fun to bounce the ball between fingers. The palm was initially boring on its own, so I gave it a big bomb. It adds a distinct feeling between the top and bottom halves."},{"name":"Blinky","size":20,"bricks":"____________________________gggg______________ggrrrrgg___________grrrrrrrrg_________grrrrrrrrrrg_______grrrWWrrrrWWrg______grrWWWWrrWWWWg______grrWWbbrrWWbbg_____grrrWWbbrrWWbbrg____grrrrWWrrrrWWrrg____grrrrrrrrrrrrrrg____grrrrrrrrrrrrrrg____grrrrrrrrrrrrrrg____grrrrrrrrrrrrrrg____grrgrrrggrrrgrrg____grg_grg__grg_grg_____g___g____g___g_______________________________________________________________","credit":"Suggested by Big Goober. The red ghost, Blinky, from the arcade game \\"Pac Man\\""}]'); },{}],"iyP6E":[function(require,module,exports,__globalThis) { -module.exports = JSON.parse("\"29092809\""); +module.exports = JSON.parse("\"29095000\""); },{}],"1u3Dx":[function(require,module,exports,__globalThis) { var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); @@ -2681,11 +2681,11 @@ const rawUpgrades = [ max: 4, name: (0, _i18N.t)("upgrades.passive_income.name"), help: (lvl)=>(0, _i18N.t)("upgrades.passive_income.tooltip", { - time: lvl * 0.10 - 0.05, + time: lvl * 0.1 - 0.05, lvl }), fullHelp: (lvl)=>(0, _i18N.t)("upgrades.passive_income.verbose_description", { - time: lvl * 0.10 - 0.05, + time: lvl * 0.1 - 0.05, lvl }) }, @@ -3327,7 +3327,7 @@ const options = { help: (0, _i18N.t)("settings.sounds_help") }, "mobile-mode": { - default: window.innerHeight > window.innerWidth || 'ontouchstart' in window || navigator.maxTouchPoints > 0, + default: window.innerHeight > window.innerWidth || "ontouchstart" in window || navigator.maxTouchPoints > 0, name: (0, _i18N.t)("settings.mobile"), help: (0, _i18N.t)("settings.mobile_help") }, @@ -5905,7 +5905,7 @@ function hideAnyTooltip() { } const tooltip = document.getElementById("tooltip"); function setupMobileTooltips(tooltip) { - tooltip.className = 'mobile'; + tooltip.className = "mobile"; function openTooltip(e) { hideAnyTooltip(); const hovering = e.target; @@ -5939,7 +5939,7 @@ function setupMobileTooltips(tooltip) { document.body.addEventListener("contextmenu", ignoreClick, true); } function setupDesktopTooltips(tooltip) { - tooltip.className = 'desktop'; + tooltip.className = "desktop"; function updateTooltipPosition(e) { tooltip.style.transform = `translate(${e.clientX}px,${e.clientY}px) translate(${e.clientX > window.innerWidth / 2 ? "-100%" : "0"},${e.clientY > window.innerHeight * 2 / 3 ? "-100%" : "20px"})`; } @@ -6171,7 +6171,7 @@ async function editRawLevelList(nth, color = "W") { }); return; } - if (action === "copy" || action === 'show_code') { + if (action === "copy" || action === "show_code") { let text = "```\n[" + (level.name || "unnamed level")?.replace(/\[|\]/gi, " ") + "]"; bricks.forEach((b, bi)=>{ if (!(bi % level.size)) text += "\n"; @@ -6180,12 +6180,12 @@ async function editRawLevelList(nth, color = "W") { text += "\n[" + (level.credit?.replace(/\[|\]/gi, " ") || "Missing credits") + "]\n```"; if (action === "copy") try { await navigator.clipboard.writeText(text); - (0, _toast.toast)((0, _i18N.t)('editor.editing.copied')); + (0, _toast.toast)((0, _i18N.t)("editor.editing.copied")); } catch (e) { - if ('message' in e) (0, _toast.toast)(e.message); + if ("message" in e) (0, _toast.toast)(e.message); } else await (0, _asyncAlert.asyncAlert)({ - title: (0, _i18N.t)('editor.editing.show_code'), + title: (0, _i18N.t)("editor.editing.show_code"), content: [ `
${text}
@@ -6406,7 +6406,7 @@ function upgradeName(id) { } },{"./loadGameData":"l1B4x","./getLevelBackground":"7OIPf","./i18n/i18n":"eNPRm","./data/unlockConditions.json":"glZU2","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"glZU2":[function(require,module,exports,__globalThis) { -module.exports = JSON.parse('{"71 mini":{"minScore":0,"required":[],"forbidden":[]},"Butterfly":{"minScore":0,"required":[],"forbidden":[]},"Castle":{"minScore":0,"required":[],"forbidden":[]},"Eyes":{"minScore":0,"required":[],"forbidden":[]},"Creeper":{"minScore":0,"required":[],"forbidden":[]},"Stairs":{"minScore":0,"required":[],"forbidden":[]},"Dots":{"minScore":0,"required":[],"forbidden":[]},"Lines":{"minScore":0,"required":[],"forbidden":[]},"Heart":{"minScore":0,"required":[],"forbidden":[]},"Swiss":{"minScore":0,"required":[],"forbidden":[]},"Germany":{"minScore":0,"required":[],"forbidden":[]},"France":{"minScore":100,"required":[],"forbidden":[]},"Smiley":{"minScore":200,"required":[],"forbidden":[]},"Labyrinthe":{"minScore":300,"required":[],"forbidden":[]},"Temple":{"minScore":400,"required":[],"forbidden":[]},"Pacman":{"minScore":500,"required":[],"forbidden":[]},"Ship":{"minScore":600,"required":[],"forbidden":[]},"We come in peace":{"minScore":700,"required":[],"forbidden":[]},"Space mushroom":{"minScore":800,"required":[],"forbidden":[]},"Wololo":{"minScore":900,"required":[],"forbidden":[]},"Small heart":{"minScore":1000,"required":[],"forbidden":[]},"Eye":{"minScore":1100,"required":["streak_shots"],"forbidden":["base_combo"]},"Enderman":{"minScore":1200,"required":["streak_shots"],"forbidden":["viscosity"]},"Mushroom":{"minScore":1300,"required":["streak_shots"],"forbidden":["base_combo"]},"Tulip":{"minScore":1400,"required":["viscosity"],"forbidden":["left_is_lava"]},"Chain":{"minScore":1500,"required":["left_is_lava"],"forbidden":["right_is_lava"]},"Marion":{"minScore":1600,"required":["viscosity"],"forbidden":["left_is_lava"]},"Renan":{"minScore":1700,"required":["viscosity"],"forbidden":["skip_last"]},"Violet Pairs":{"minScore":1800,"required":["skip_last"],"forbidden":["base_combo"]},"Red Cups":{"minScore":1900,"required":["skip_last"],"forbidden":["viscosity"]},"Cactus":{"minScore":2000,"required":["right_is_lava"],"forbidden":["skip_last"]},"Sunny Face":{"minScore":2100,"required":["streak_shots","base_combo"],"forbidden":["smaller_puck","skip_last"]},"Mountain":{"minScore":2200,"required":["smaller_puck","streak_shots"],"forbidden":["left_is_lava","skip_last"]},"Dollar":{"minScore":2300,"required":["pierce","smaller_puck"],"forbidden":["left_is_lava","base_combo"]},"Waves":{"minScore":2400,"required":["left_is_lava","smaller_puck"],"forbidden":["picky_eater","pierce"]},"Box":{"minScore":2500,"required":["left_is_lava","picky_eater"],"forbidden":["smaller_puck","base_combo"]},"Rose":{"minScore":2600,"required":["compound_interest","picky_eater"],"forbidden":["left_is_lava","base_combo"]},"Time":{"minScore":2700,"required":["picky_eater","right_is_lava"],"forbidden":["pierce","left_is_lava"]},"Watermelon":{"minScore":2800,"required":["hot_start","base_combo"],"forbidden":["pierce","right_is_lava"]},"Worms":{"minScore":2900,"required":["picky_eater","hot_start"],"forbidden":["right_is_lava","pierce"]},"Ocean Sunrise":{"minScore":3000,"required":["smaller_puck","hot_start"],"forbidden":["streak_shots","telekinesis"]},"Crosses":{"minScore":3100,"required":["pierce","sapper"],"forbidden":["smaller_puck","compound_interest"]},"Negative space":{"minScore":3200,"required":["left_is_lava","smaller_puck"],"forbidden":["right_is_lava","hot_start"]},"UK":{"minScore":3300,"required":["right_is_lava","left_is_lava"],"forbidden":["base_combo","smaller_puck"]},"Greece":{"minScore":3400,"required":["left_is_lava","right_is_lava"],"forbidden":["telekinesis","hot_start"]},"Russia":{"minScore":3500,"required":["compound_interest","bigger_explosions"],"forbidden":["sapper","pierce"]},"Ukraine":{"minScore":3600,"required":["pierce","sapper"],"forbidden":["base_combo","bigger_explosions"]},"Poland":{"minScore":3700,"required":["viscosity","picky_eater"],"forbidden":["skip_last","pierce"]},"Yellow 71":{"minScore":3800,"required":["base_combo","viscosity"],"forbidden":["picky_eater","skip_last"]},"71 on white":{"minScore":3900,"required":["viscosity","picky_eater"],"forbidden":["compound_interest","skip_last"]},"Blue 71":{"minScore":4000,"required":["compound_interest","pierce_color"],"forbidden":["left_is_lava","viscosity"]},"Seventy one":{"minScore":4100,"required":["viscosity","base_combo"],"forbidden":["left_is_lava","pierce_color"]},"B71":{"minScore":4200,"required":["skip_last","viscosity"],"forbidden":["telekinesis","left_is_lava"]},"Pig":{"minScore":4300,"required":["skip_last","viscosity"],"forbidden":["ball_repulse_ball","telekinesis"]},"Big Pig":{"minScore":4400,"required":["pierce","sapper"],"forbidden":["skip_last","compound_interest"]},"Donkey Kong":{"minScore":4500,"required":["ball_attract_ball","right_is_lava"],"forbidden":["bigger_explosions","skip_last"]},"Banana":{"minScore":4600,"required":["right_is_lava","soft_reset"],"forbidden":["base_combo","skip_last"]},"Fox":{"minScore":4700,"required":["ball_repulse_ball","puck_repulse_ball"],"forbidden":["right_is_lava","skip_last"]},"Wiki":{"minScore":4800,"required":["base_combo","sapper"],"forbidden":["compound_interest","pierce"]},"Baby Dog":{"minScore":4900,"required":["bigger_explosions","pierce"],"forbidden":["sapper","compound_interest"]},"dog 21":{"minScore":5000,"required":["ball_attract_ball","respawn"],"forbidden":["telekinesis","right_is_lava"]},"A":{"minScore":5100,"required":["telekinesis","base_combo","sturdy_bricks"],"forbidden":["hot_start","top_is_lava","bigger_puck"]},"B":{"minScore":5200,"required":["pierce","hot_start","telekinesis"],"forbidden":["sapper","ball_repulse_ball","puck_repulse_ball"]},"C":{"minScore":5300,"required":["hot_start","telekinesis","compound_interest"],"forbidden":["top_is_lava","bigger_puck","bigger_explosions"]},"D":{"minScore":5400,"required":["hot_start","bigger_explosions","ball_attract_ball"],"forbidden":["telekinesis","soft_reset","compound_interest"]},"e":{"minScore":5500,"required":["respawn","hot_start","telekinesis"],"forbidden":["ball_attract_ball","top_is_lava","bigger_puck"]},"Elephant":{"minScore":5600,"required":["ball_repulse_ball","puck_repulse_ball","soft_reset"],"forbidden":["base_combo","sapper","telekinesis"]},"Orca":{"minScore":5700,"required":["pierce","sapper","respawn"],"forbidden":["concave_puck","telekinesis","compound_interest"]},"Shark":{"minScore":5800,"required":["bigger_explosions","compound_interest","base_combo"],"forbidden":["right_is_lava","concave_puck","ball_attract_ball"]},"Bird":{"minScore":5900,"required":["right_is_lava","concave_puck","sturdy_bricks"],"forbidden":["ball_attract_ball","streak_shots","soft_reset"]},"Tux":{"minScore":6000,"required":["pierce","coin_magnet","bigger_puck"],"forbidden":["sapper","top_is_lava","helium"]},"Armenia":{"minScore":6100,"required":["top_is_lava","respawn","bigger_puck"],"forbidden":["base_combo","coin_magnet","ball_repulse_ball"]},"Austria":{"minScore":6200,"required":["top_is_lava","telekinesis","bigger_puck"],"forbidden":["coin_magnet","viscosity","unbounded"]},"Benin":{"minScore":6300,"required":["telekinesis","right_is_lava","bigger_explosions"],"forbidden":["viscosity","top_is_lava","unbounded"]},"Botswana":{"minScore":6400,"required":["viscosity","telekinesis","unbounded"],"forbidden":["sturdy_bricks","soft_reset","right_is_lava"]},"Bulgaria":{"minScore":6500,"required":["helium","puck_repulse_ball","unbounded"],"forbidden":["ball_repulse_ball","viscosity","pierce"]},"Canada":{"minScore":6600,"required":["skip_last","respawn","base_combo"],"forbidden":["asceticism","unbounded","telekinesis"]},"Chad":{"minScore":6700,"required":["compound_interest","bigger_explosions","skip_last"],"forbidden":["concave_puck","streak_shots","telekinesis"]},"China":{"minScore":6800,"required":["nbricks","concave_puck","streak_shots"],"forbidden":["ball_attract_ball","skip_last","base_combo"]},"Colombia":{"minScore":6900,"required":["streak_shots","smaller_puck","concave_puck"],"forbidden":["puck_repulse_ball","ball_repulse_ball","sapper"]},"Republic of the Congo":{"minScore":7000,"required":["ball_repulse_ball","puck_repulse_ball","coin_magnet"],"forbidden":["bigger_puck","top_is_lava","skip_last"]},"C\xf4te d\'Ivoire":{"minScore":7100,"required":["coin_magnet","bigger_puck","top_is_lava"],"forbidden":["base_combo","etherealcoins","telekinesis"]},"Denmark":{"minScore":7200,"required":["bigger_explosions","coin_magnet","etherealcoins"],"forbidden":["respawn","bigger_puck","top_is_lava"]},"El Salvador":{"minScore":7300,"required":["bigger_puck","top_is_lava","helium"],"forbidden":["pierce","coin_magnet","sapper"]},"Egypt":{"minScore":7400,"required":["zen","top_is_lava","soft_reset"],"forbidden":["bigger_puck","telekinesis","puck_repulse_ball"]},"Estonia":{"minScore":7500,"required":["zen","telekinesis","hot_start"],"forbidden":["top_is_lava","bigger_puck","concave_puck"]},"Finland":{"minScore":7600,"required":["concave_puck","hot_start","telekinesis"],"forbidden":["zen","compound_interest","base_combo"]},"Gabon":{"minScore":7700,"required":["respawn","ball_attract_ball","zen"],"forbidden":["streak_shots","sturdy_bricks","hot_start"]},"Georgia":{"minScore":7800,"required":["helium","zen","smaller_puck"],"forbidden":["pierce","telekinesis","sapper"]},"Guinea":{"minScore":7900,"required":["zen","nbricks","smaller_puck"],"forbidden":["pierce_color","left_is_lava","ball_repulse_ball"]},"Indonesia":{"minScore":8000,"required":["trampoline","zen","right_is_lava"],"forbidden":["nbricks","coin_magnet","hot_start"]},"Pingwin":{"minScore":8100,"required":["zen","compound_interest","pierce"],"forbidden":["right_is_lava","sturdy_bricks","helium"]},"Dog 8":{"minScore":8200,"required":["zen","ball_attract_ball","coin_magnet"],"forbidden":["sacrifice","sturdy_bricks","bigger_puck"]},"Sunglasses":{"minScore":8300,"required":["zen","sacrifice","coin_magnet"],"forbidden":["respawn","bigger_puck","top_is_lava"]},"Balloon":{"minScore":8400,"required":["soft_reset","coin_magnet","zen"],"forbidden":["concave_puck","sacrifice","bigger_puck"]},"Opening":{"minScore":8500,"required":["streak_shots","bigger_puck","top_is_lava"],"forbidden":["zen","etherealcoins","coin_magnet"]},"Stripes":{"minScore":8600,"required":["helium","base_combo","zen"],"forbidden":["top_is_lava","ball_attract_ball","bigger_puck"]},"You are here":{"minScore":8700,"required":["zen","forgiving","telekinesis"],"forbidden":["smaller_puck","viscosity","top_is_lava"]},"Gear":{"minScore":8800,"required":["pierce_color","telekinesis","left_is_lava"],"forbidden":["unbounded","respawn","zen"]},"Play":{"minScore":8900,"required":["zen","right_is_lava","skip_last"],"forbidden":["ball_attracts_coins","telekinesis","unbounded"]},"City":{"minScore":9000,"required":["passive_income","asceticism","soft_reset"],"forbidden":["hot_start","ball_repulse_ball","base_combo"]},"Wiggle":{"minScore":9100,"required":["right_is_lava","trampoline","ball_attracts_coins"],"forbidden":["sturdy_bricks","hot_start","compound_interest"]},"Graph":{"minScore":9200,"required":["hot_start","shocks","sapper"],"forbidden":["pierce","ball_attract_ball","ball_attracts_coins"]},"Lightbulb":{"minScore":9300,"required":["hot_start","passive_income","helium"],"forbidden":["trampoline","ball_attracts_coins","pierce"]},"Note":{"minScore":9400,"required":["ball_repulse_ball","puck_repulse_ball","nbricks"],"forbidden":["hot_start","respawn","etherealcoins"]},"Rocket":{"minScore":9500,"required":["etherealcoins","soft_reset","asceticism"],"forbidden":["coin_magnet","hot_start","bigger_puck"]},"Abstract":{"minScore":9600,"required":["bigger_explosions","compound_interest","etherealcoins"],"forbidden":["coin_magnet","passive_income","nbricks"]},"Fingerprint":{"minScore":9700,"required":["pierce","sapper","shocks"],"forbidden":["base_combo","implosions","helium"]},"Leaf":{"minScore":9800,"required":["concave_puck","sacrifice","puck_repulse_ball"],"forbidden":["coin_magnet","trampoline","ball_repulse_ball"]},"Abstract 2":{"minScore":9900,"required":["coin_magnet","streak_shots","sacrifice"],"forbidden":["bigger_puck","top_is_lava","right_is_lava"]},"Abstract 3":{"minScore":10000,"required":["sacrifice","nbricks","etherealcoins"],"forbidden":["shocks","sapper","asceticism"]},"Abstract 4":{"minScore":10100,"required":["trampoline","bigger_explosions","sacrifice"],"forbidden":["ball_attracts_coins","ghost_coins","ball_attract_ball"]},"Abstract 5":{"minScore":10200,"required":["ball_attracts_coins","implosions","forgiving"],"forbidden":["viscosity","base_combo","unbounded"]},"Abstract 6":{"minScore":10300,"required":["puck_repulse_ball","ball_repulse_ball","forgiving"],"forbidden":["viscosity","unbounded","passive_income"]},"Hemiola":{"minScore":10400,"required":["limitless","unbounded","viscosity"],"forbidden":["right_is_lava","forgiving","sturdy_bricks"]},"Obigre":{"minScore":10500,"required":["sapper","shocks","soft_reset"],"forbidden":["bigger_explosions","pierce","skip_last"]},"Noodlemire":{"minScore":10600,"required":["skip_last","concave_puck","passive_income"],"forbidden":["ball_attract_ball","side_flip","side_kick"]},"Bearded axe":{"minScore":10700,"required":["base_combo","streak_shots","side_flip"],"forbidden":["side_kick","implosions","concave_puck"]},"Lebanon":{"minScore":10800,"required":["side_kick","side_flip","etherealcoins"],"forbidden":["smaller_puck","streak_shots","trampoline"]},"Spain":{"minScore":10900,"required":["smaller_puck","passive_income","compound_interest"],"forbidden":["fountain_toss","side_kick","side_flip"]},"Uzbekistan":{"minScore":11000,"required":["picky_eater","ghost_coins","bigger_explosions"],"forbidden":["base_combo","clairvoyant","implosions"]},"Pakistan":{"minScore":11100,"required":["nbricks","ghost_coins","trampoline"],"forbidden":["picky_eater","clairvoyant","corner_shot"]},"Korea":{"minScore":11200,"required":["puck_repulse_ball","ball_attracts_coins","ball_repulse_ball"],"forbidden":["ghost_coins","picky_eater","etherealcoins"]},"Chile":{"minScore":11300,"required":["shocks","sapper","pierce"],"forbidden":["etherealcoins","ball_attracts_coins","ghost_coins"]},"T\xfcrkiye":{"minScore":11400,"required":["compound_interest","fountain_toss","concave_puck"],"forbidden":["bigger_explosions","superhot","respawn"]},"Taj Mahal":{"minScore":11500,"required":["asceticism","soft_reset","streak_shots"],"forbidden":["concave_puck","ball_attract_ball","hot_start"]},"Abstract 7":{"minScore":11600,"required":["hot_start","nbricks","streak_shots"],"forbidden":["trampoline","smaller_puck","superhot"]},"Abstract 9":{"minScore":11700,"required":["implosions","smaller_puck","right_is_lava"],"forbidden":["base_combo","sturdy_bricks","hot_start"]},"Crosshair":{"minScore":11800,"required":["pierce","pierce_color","left_is_lava"],"forbidden":["sapper","transparency","shocks"]},"Abstract 10":{"minScore":11900,"required":["transparency","ball_attract_ball","left_is_lava"],"forbidden":["pierce_color","rainbow","passive_income"]},"Face":{"minScore":12000,"required":["rainbow","corner_shot","bricks_attract_coins"],"forbidden":["base_combo","clairvoyant","respawn"]},"Eiffel tower":{"minScore":12100,"required":["shocks","sapper","clairvoyant"],"forbidden":["passive_income","picky_eater","pierce"]},"Abstract 11":{"minScore":12200,"required":["picky_eater","nbricks","addiction"],"forbidden":["minefield","sturdy_bricks","ghost_coins"]},"Abstract 12":{"minScore":12300,"required":["ghost_coins","sacrifice","ball_attracts_coins"],"forbidden":["concave_puck","picky_eater","compound_interest"]},"Abstract 13":{"minScore":12400,"required":["ball_attract_ball","streak_shots","ghost_coins"],"forbidden":["passive_income","sacrifice","picky_eater"]},"Abstract 14":{"minScore":12500,"required":["smaller_puck","asceticism","rainbow"],"forbidden":["bricks_attract_ball","soft_reset","respawn"]},"S":{"minScore":12600,"required":["pierce","sapper","shocks"],"forbidden":["etherealcoins","trampoline","pierce_color"]},"Abstract 15":{"minScore":12700,"required":["forgiving","viscosity"],"forbidden":["fountain_toss","transparency","left_is_lava"]},"Mario!":{"minScore":12800,"required":["unbounded","limitless","viscosity"],"forbidden":["forgiving","skip_last","ball_attract_ball"]},"Minesweeper":{"minScore":12900,"required":["ottawa_treaty","skip_last","unbounded"],"forbidden":["limitless","viscosity","forgiving"]},"Target":{"minScore":13000,"required":["skip_last","implosions","base_combo"],"forbidden":["etherealcoins","reach","three_cushion"]},"The Boys":{"minScore":13100,"required":["concave_puck","respawn","rainbow"],"forbidden":["reach","corner_shot","skip_last"]},"A Very Dangerous High-Five":{"minScore":13200,"required":["side_kick","side_flip","corner_shot"],"forbidden":["streak_shots","reach","clairvoyant"]},"Blinky":{"required":["clairvoyant","reach","double_or_nothing"],"forbidden":["nbricks","corner_shot","smaller_puck"],"minScore":13300}}'); +module.exports = JSON.parse('{"71 mini":{"minScore":0,"required":[],"forbidden":[]},"Butterfly":{"minScore":0,"required":[],"forbidden":[]},"Castle":{"minScore":0,"required":[],"forbidden":[]},"Eyes":{"minScore":0,"required":[],"forbidden":[]},"Creeper":{"minScore":0,"required":[],"forbidden":[]},"Stairs":{"minScore":0,"required":[],"forbidden":[]},"Dots":{"minScore":0,"required":[],"forbidden":[]},"Lines":{"minScore":0,"required":[],"forbidden":[]},"Heart":{"minScore":0,"required":[],"forbidden":[]},"Swiss":{"minScore":0,"required":[],"forbidden":[]},"Germany":{"minScore":0,"required":[],"forbidden":[]},"France":{"minScore":100,"required":[],"forbidden":[]},"Smiley":{"minScore":200,"required":[],"forbidden":[]},"Labyrinthe":{"minScore":300,"required":[],"forbidden":[]},"Temple":{"minScore":400,"required":[],"forbidden":[]},"Pacman":{"minScore":500,"required":[],"forbidden":[]},"Ship":{"minScore":600,"required":[],"forbidden":[]},"We come in peace":{"minScore":700,"required":[],"forbidden":[]},"Space mushroom":{"minScore":800,"required":[],"forbidden":[]},"Wololo":{"minScore":900,"required":[],"forbidden":[]},"Small heart":{"minScore":1000,"required":[],"forbidden":[]},"Eye":{"minScore":1100,"required":["streak_shots"],"forbidden":["base_combo"]},"Enderman":{"minScore":1200,"required":["streak_shots"],"forbidden":["viscosity"]},"Mushroom":{"minScore":1300,"required":["streak_shots"],"forbidden":["base_combo"]},"Tulip":{"minScore":1400,"required":["viscosity"],"forbidden":["left_is_lava"]},"Chain":{"minScore":1500,"required":["left_is_lava"],"forbidden":["right_is_lava"]},"Marion":{"minScore":1600,"required":["viscosity"],"forbidden":["left_is_lava"]},"Renan":{"minScore":1700,"required":["viscosity"],"forbidden":["skip_last"]},"Violet Pairs":{"minScore":1800,"required":["skip_last"],"forbidden":["base_combo"]},"Red Cups":{"minScore":1900,"required":["skip_last"],"forbidden":["viscosity"]},"Cactus":{"minScore":2000,"required":["right_is_lava"],"forbidden":["skip_last"]},"Sunny Face":{"minScore":2100,"required":["streak_shots","base_combo"],"forbidden":["smaller_puck","skip_last"]},"Mountain":{"minScore":2200,"required":["smaller_puck","streak_shots"],"forbidden":["left_is_lava","skip_last"]},"Dollar":{"minScore":2300,"required":["pierce","smaller_puck"],"forbidden":["left_is_lava","base_combo"]},"Waves":{"minScore":2400,"required":["left_is_lava","smaller_puck"],"forbidden":["picky_eater","pierce"]},"Box":{"minScore":2500,"required":["left_is_lava","picky_eater"],"forbidden":["smaller_puck","base_combo"]},"Rose":{"minScore":2600,"required":["compound_interest","picky_eater"],"forbidden":["left_is_lava","base_combo"]},"Time":{"minScore":2700,"required":["picky_eater","right_is_lava"],"forbidden":["pierce","left_is_lava"]},"Watermelon":{"minScore":2800,"required":["hot_start","base_combo"],"forbidden":["pierce","right_is_lava"]},"Worms":{"minScore":2900,"required":["picky_eater","hot_start"],"forbidden":["right_is_lava","pierce"]},"Ocean Sunrise":{"minScore":3000,"required":["smaller_puck","hot_start"],"forbidden":["streak_shots","telekinesis"]},"Crosses":{"minScore":3100,"required":["pierce","sapper"],"forbidden":["smaller_puck","compound_interest"]},"Negative space":{"minScore":3200,"required":["left_is_lava","smaller_puck"],"forbidden":["right_is_lava","hot_start"]},"UK":{"minScore":3300,"required":["right_is_lava","left_is_lava"],"forbidden":["base_combo","smaller_puck"]},"Greece":{"minScore":3400,"required":["left_is_lava","right_is_lava"],"forbidden":["telekinesis","hot_start"]},"Russia":{"minScore":3500,"required":["compound_interest","bigger_explosions"],"forbidden":["sapper","pierce"]},"Ukraine":{"minScore":3600,"required":["pierce","sapper"],"forbidden":["base_combo","bigger_explosions"]},"Poland":{"minScore":3700,"required":["viscosity","picky_eater"],"forbidden":["skip_last","pierce"]},"Yellow 71":{"minScore":3800,"required":["base_combo","viscosity"],"forbidden":["picky_eater","skip_last"]},"71 on white":{"minScore":3900,"required":["viscosity","picky_eater"],"forbidden":["compound_interest","skip_last"]},"Blue 71":{"minScore":4000,"required":["compound_interest","pierce_color"],"forbidden":["left_is_lava","viscosity"]},"Seventy one":{"minScore":4100,"required":["viscosity","base_combo"],"forbidden":["left_is_lava","pierce_color"]},"B71":{"minScore":4200,"required":["skip_last","viscosity"],"forbidden":["telekinesis","left_is_lava"]},"Pig":{"minScore":4300,"required":["skip_last","viscosity"],"forbidden":["ball_repulse_ball","telekinesis"]},"Big Pig":{"minScore":4400,"required":["pierce","sapper"],"forbidden":["skip_last","compound_interest"]},"Donkey Kong":{"minScore":4500,"required":["ball_attract_ball","right_is_lava"],"forbidden":["bigger_explosions","skip_last"]},"Banana":{"minScore":4600,"required":["right_is_lava","soft_reset"],"forbidden":["base_combo","skip_last"]},"Fox":{"minScore":4700,"required":["ball_repulse_ball","puck_repulse_ball"],"forbidden":["right_is_lava","skip_last"]},"Wiki":{"minScore":4800,"required":["base_combo","sapper"],"forbidden":["compound_interest","pierce"]},"Baby Dog":{"minScore":4900,"required":["bigger_explosions","pierce"],"forbidden":["sapper","compound_interest"]},"dog 21":{"minScore":5000,"required":["ball_attract_ball","respawn"],"forbidden":["telekinesis","right_is_lava"]},"A":{"minScore":5100,"required":["telekinesis","base_combo","sturdy_bricks"],"forbidden":["hot_start","top_is_lava","bigger_puck"]},"B":{"minScore":5200,"required":["pierce","hot_start","telekinesis"],"forbidden":["sapper","ball_repulse_ball","puck_repulse_ball"]},"C":{"minScore":5300,"required":["hot_start","telekinesis","compound_interest"],"forbidden":["top_is_lava","bigger_puck","bigger_explosions"]},"D":{"minScore":5400,"required":["hot_start","bigger_explosions","ball_attract_ball"],"forbidden":["telekinesis","soft_reset","compound_interest"]},"e":{"minScore":5500,"required":["respawn","hot_start","telekinesis"],"forbidden":["ball_attract_ball","top_is_lava","bigger_puck"]},"Elephant":{"minScore":5600,"required":["ball_repulse_ball","puck_repulse_ball","soft_reset"],"forbidden":["base_combo","sapper","telekinesis"]},"Orca":{"minScore":5700,"required":["pierce","sapper","respawn"],"forbidden":["concave_puck","telekinesis","compound_interest"]},"Shark":{"minScore":5800,"required":["bigger_explosions","compound_interest","base_combo"],"forbidden":["right_is_lava","concave_puck","ball_attract_ball"]},"Bird":{"minScore":5900,"required":["right_is_lava","concave_puck","sturdy_bricks"],"forbidden":["ball_attract_ball","streak_shots","soft_reset"]},"Tux":{"minScore":6000,"required":["pierce","coin_magnet","bigger_puck"],"forbidden":["sapper","top_is_lava","helium"]},"Armenia":{"minScore":6100,"required":["top_is_lava","respawn","bigger_puck"],"forbidden":["base_combo","coin_magnet","ball_repulse_ball"]},"Austria":{"minScore":6200,"required":["top_is_lava","telekinesis","bigger_puck"],"forbidden":["coin_magnet","viscosity","unbounded"]},"Benin":{"minScore":6300,"required":["telekinesis","right_is_lava","bigger_explosions"],"forbidden":["viscosity","top_is_lava","unbounded"]},"Botswana":{"minScore":6400,"required":["viscosity","telekinesis","unbounded"],"forbidden":["sturdy_bricks","soft_reset","right_is_lava"]},"Bulgaria":{"minScore":6500,"required":["helium","puck_repulse_ball","unbounded"],"forbidden":["ball_repulse_ball","viscosity","pierce"]},"Canada":{"minScore":6600,"required":["skip_last","respawn","base_combo"],"forbidden":["asceticism","unbounded","telekinesis"]},"Chad":{"minScore":6700,"required":["compound_interest","bigger_explosions","skip_last"],"forbidden":["concave_puck","streak_shots","telekinesis"]},"China":{"minScore":6800,"required":["nbricks","concave_puck","streak_shots"],"forbidden":["ball_attract_ball","skip_last","base_combo"]},"Colombia":{"minScore":6900,"required":["streak_shots","smaller_puck","concave_puck"],"forbidden":["puck_repulse_ball","ball_repulse_ball","sapper"]},"Republic of the Congo":{"minScore":7000,"required":["ball_repulse_ball","puck_repulse_ball","coin_magnet"],"forbidden":["bigger_puck","top_is_lava","skip_last"]},"C\xf4te d\'Ivoire":{"minScore":7100,"required":["coin_magnet","bigger_puck","top_is_lava"],"forbidden":["base_combo","etherealcoins","telekinesis"]},"Denmark":{"minScore":7200,"required":["bigger_explosions","coin_magnet","etherealcoins"],"forbidden":["respawn","bigger_puck","top_is_lava"]},"El Salvador":{"minScore":7300,"required":["bigger_puck","top_is_lava","helium"],"forbidden":["pierce","coin_magnet","sapper"]},"Egypt":{"minScore":7400,"required":["zen","top_is_lava","soft_reset"],"forbidden":["bigger_puck","telekinesis","puck_repulse_ball"]},"Estonia":{"minScore":7500,"required":["zen","telekinesis","hot_start"],"forbidden":["top_is_lava","bigger_puck","concave_puck"]},"Finland":{"minScore":7600,"required":["concave_puck","hot_start","telekinesis"],"forbidden":["zen","compound_interest","base_combo"]},"Gabon":{"minScore":7700,"required":["respawn","ball_attract_ball","zen"],"forbidden":["streak_shots","sturdy_bricks","hot_start"]},"Georgia":{"minScore":7800,"required":["helium","zen","smaller_puck"],"forbidden":["pierce","telekinesis","sapper"]},"Guinea":{"minScore":7900,"required":["zen","nbricks","smaller_puck"],"forbidden":["pierce_color","left_is_lava","ball_repulse_ball"]},"Indonesia":{"minScore":8000,"required":["trampoline","zen","right_is_lava"],"forbidden":["nbricks","coin_magnet","hot_start"]},"Pingwin":{"minScore":8100,"required":["zen","compound_interest","pierce"],"forbidden":["right_is_lava","sturdy_bricks","helium"]},"Dog 8":{"minScore":8200,"required":["zen","ball_attract_ball","coin_magnet"],"forbidden":["sacrifice","sturdy_bricks","bigger_puck"]},"Sunglasses":{"minScore":8300,"required":["zen","sacrifice","coin_magnet"],"forbidden":["respawn","bigger_puck","top_is_lava"]},"Balloon":{"minScore":8400,"required":["soft_reset","coin_magnet","zen"],"forbidden":["concave_puck","sacrifice","bigger_puck"]},"Opening":{"minScore":8500,"required":["streak_shots","bigger_puck","top_is_lava"],"forbidden":["zen","etherealcoins","coin_magnet"]},"Stripes":{"minScore":8600,"required":["helium","base_combo","zen"],"forbidden":["top_is_lava","ball_attract_ball","bigger_puck"]},"You are here":{"minScore":8700,"required":["zen","forgiving","telekinesis"],"forbidden":["smaller_puck","viscosity","top_is_lava"]},"Gear":{"minScore":8800,"required":["pierce_color","telekinesis","left_is_lava"],"forbidden":["unbounded","respawn","zen"]},"Play":{"minScore":8900,"required":["zen","right_is_lava","skip_last"],"forbidden":["ball_attracts_coins","telekinesis","unbounded"]},"City":{"minScore":9000,"required":["passive_income","asceticism","soft_reset"],"forbidden":["hot_start","ball_repulse_ball","base_combo"]},"Wiggle":{"minScore":9100,"required":["right_is_lava","trampoline","ball_attracts_coins"],"forbidden":["sturdy_bricks","hot_start","compound_interest"]},"Graph":{"minScore":9200,"required":["hot_start","shocks","sapper"],"forbidden":["pierce","ball_attract_ball","ball_attracts_coins"]},"Lightbulb":{"minScore":9300,"required":["hot_start","passive_income","helium"],"forbidden":["trampoline","ball_attracts_coins","pierce"]},"Note":{"minScore":9400,"required":["ball_repulse_ball","puck_repulse_ball","nbricks"],"forbidden":["hot_start","respawn","etherealcoins"]},"Rocket":{"minScore":9500,"required":["etherealcoins","soft_reset","asceticism"],"forbidden":["coin_magnet","hot_start","bigger_puck"]},"Abstract":{"minScore":9600,"required":["bigger_explosions","compound_interest","etherealcoins"],"forbidden":["coin_magnet","passive_income","nbricks"]},"Fingerprint":{"minScore":9700,"required":["pierce","sapper","shocks"],"forbidden":["base_combo","implosions","helium"]},"Leaf":{"minScore":9800,"required":["concave_puck","sacrifice","puck_repulse_ball"],"forbidden":["coin_magnet","trampoline","ball_repulse_ball"]},"Abstract 2":{"minScore":9900,"required":["coin_magnet","streak_shots","sacrifice"],"forbidden":["bigger_puck","top_is_lava","right_is_lava"]},"Abstract 3":{"minScore":10000,"required":["sacrifice","nbricks","etherealcoins"],"forbidden":["shocks","sapper","asceticism"]},"Abstract 4":{"minScore":10100,"required":["trampoline","bigger_explosions","sacrifice"],"forbidden":["ball_attracts_coins","ghost_coins","ball_attract_ball"]},"Abstract 5":{"minScore":10200,"required":["ball_attracts_coins","implosions","forgiving"],"forbidden":["viscosity","base_combo","unbounded"]},"Abstract 6":{"minScore":10300,"required":["puck_repulse_ball","ball_repulse_ball","forgiving"],"forbidden":["viscosity","unbounded","passive_income"]},"Hemiola":{"minScore":10400,"required":["limitless","unbounded","viscosity"],"forbidden":["right_is_lava","forgiving","sturdy_bricks"]},"Obigre":{"minScore":10500,"required":["sapper","shocks","soft_reset"],"forbidden":["bigger_explosions","pierce","skip_last"]},"Noodlemire":{"minScore":10600,"required":["skip_last","concave_puck","passive_income"],"forbidden":["ball_attract_ball","side_flip","side_kick"]},"Bearded axe":{"minScore":10700,"required":["base_combo","streak_shots","side_flip"],"forbidden":["side_kick","implosions","concave_puck"]},"Lebanon":{"minScore":10800,"required":["side_kick","side_flip","etherealcoins"],"forbidden":["smaller_puck","streak_shots","trampoline"]},"Spain":{"minScore":10900,"required":["smaller_puck","passive_income","compound_interest"],"forbidden":["fountain_toss","side_kick","side_flip"]},"Uzbekistan":{"minScore":11000,"required":["picky_eater","ghost_coins","bigger_explosions"],"forbidden":["base_combo","clairvoyant","implosions"]},"Pakistan":{"minScore":11100,"required":["nbricks","ghost_coins","trampoline"],"forbidden":["picky_eater","clairvoyant","corner_shot"]},"Korea":{"minScore":11200,"required":["puck_repulse_ball","ball_attracts_coins","ball_repulse_ball"],"forbidden":["ghost_coins","picky_eater","etherealcoins"]},"Chile":{"minScore":11300,"required":["shocks","sapper","pierce"],"forbidden":["etherealcoins","ball_attracts_coins","ghost_coins"]},"T\xfcrkiye":{"minScore":11400,"required":["compound_interest","fountain_toss","concave_puck"],"forbidden":["bigger_explosions","superhot","respawn"]},"Taj Mahal":{"minScore":11500,"required":["asceticism","soft_reset","streak_shots"],"forbidden":["concave_puck","ball_attract_ball","hot_start"]},"Abstract 7":{"minScore":11600,"required":["hot_start","nbricks","streak_shots"],"forbidden":["trampoline","smaller_puck","superhot"]},"Abstract 9":{"minScore":11700,"required":["implosions","smaller_puck","right_is_lava"],"forbidden":["base_combo","sturdy_bricks","hot_start"]},"Crosshair":{"minScore":11800,"required":["pierce","pierce_color","left_is_lava"],"forbidden":["sapper","transparency","shocks"]},"Abstract 10":{"minScore":11900,"required":["transparency","ball_attract_ball","left_is_lava"],"forbidden":["pierce_color","rainbow","passive_income"]},"Face":{"minScore":12000,"required":["rainbow","corner_shot","bricks_attract_coins"],"forbidden":["base_combo","clairvoyant","respawn"]},"Eiffel tower":{"minScore":12100,"required":["shocks","sapper","clairvoyant"],"forbidden":["passive_income","picky_eater","pierce"]},"Abstract 11":{"minScore":12200,"required":["picky_eater","nbricks","addiction"],"forbidden":["minefield","sturdy_bricks","ghost_coins"]},"Abstract 12":{"minScore":12300,"required":["ghost_coins","sacrifice","ball_attracts_coins"],"forbidden":["concave_puck","picky_eater","compound_interest"]},"Abstract 13":{"minScore":12400,"required":["ball_attract_ball","streak_shots","ghost_coins"],"forbidden":["passive_income","sacrifice","picky_eater"]},"Abstract 14":{"minScore":12500,"required":["smaller_puck","asceticism","rainbow"],"forbidden":["bricks_attract_ball","soft_reset","respawn"]},"S":{"minScore":12600,"required":["pierce","sapper","shocks"],"forbidden":["etherealcoins","trampoline","pierce_color"]},"Abstract 15":{"minScore":12700,"required":["forgiving","viscosity"],"forbidden":["fountain_toss","transparency","left_is_lava"]},"Mario!":{"minScore":12800,"required":["unbounded","limitless","viscosity"],"forbidden":["forgiving","skip_last","ball_attract_ball"]},"Minesweeper":{"minScore":12900,"required":["ottawa_treaty","skip_last","unbounded"],"forbidden":["limitless","viscosity","forgiving"]},"Target":{"minScore":13000,"required":["skip_last","implosions","base_combo"],"forbidden":["etherealcoins","reach","three_cushion"]},"The Boys":{"minScore":13100,"required":["concave_puck","respawn","rainbow"],"forbidden":["reach","corner_shot","skip_last"]},"A Very Dangerous High-Five":{"minScore":13200,"required":["side_kick","rainbow","corner_shot"],"forbidden":["streak_shots","reach","clairvoyant"]},"Blinky":{"required":["clairvoyant","reach","double_or_nothing"],"forbidden":["nbricks","corner_shot","smaller_puck"],"minScore":13300}}'); },{}],"ka4dG":[function(require,module,exports,__globalThis) { var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); diff --git a/src/PWA/sw-b71.js b/src/PWA/sw-b71.js index 318139f..9bfe0c3 100644 --- a/src/PWA/sw-b71.js +++ b/src/PWA/sw-b71.js @@ -1,5 +1,5 @@ // The version of the cache. -const VERSION = "29092809"; +const VERSION = "29095000"; // The name of the cache const CACHE_NAME = `breakout-71-${VERSION}`; diff --git a/src/creative.ts b/src/creative.ts index d114b00..ea966eb 100644 --- a/src/creative.ts +++ b/src/creative.ts @@ -9,15 +9,11 @@ import { restart, } from "./game"; import { asyncAlert, requiredAsyncAlert } from "./asyncAlert"; -import { - describeLevel, - highScoreText, - sumOfValues, -} from "./game_utils"; +import { describeLevel, highScoreText, sumOfValues } from "./game_utils"; import { getHistory } from "./gameOver"; import { noCreative } from "./upgrades"; import { levelIconHTML } from "./levelIcon"; -import {reasonLevelIsLocked} from "./get_level_unlock_condition"; +import { reasonLevelIsLocked } from "./get_level_unlock_condition"; export function creativeMode(gameState: GameState) { return { @@ -46,7 +42,8 @@ export async function openCreativeModePerksPicker() { while (true) { const levelOptions = [ ...allLevels.map((l, li) => { - const problem = reasonLevelIsLocked(li, l.name,getHistory(), true)?.text || ""; + const problem = + reasonLevelIsLocked(li, l.name, getHistory(), true)?.text || ""; return { icon: icons[l.name], text: l.name, diff --git a/src/data/unlockConditions.json b/src/data/unlockConditions.json index 00fe175..98ce6c1 100644 --- a/src/data/unlockConditions.json +++ b/src/data/unlockConditions.json @@ -106,1216 +106,508 @@ }, "Eye": { "minScore": 1100, - "required": [ - "streak_shots" - ], - "forbidden": [ - "base_combo" - ] + "required": ["streak_shots"], + "forbidden": ["base_combo"] }, "Enderman": { "minScore": 1200, - "required": [ - "streak_shots" - ], - "forbidden": [ - "viscosity" - ] + "required": ["streak_shots"], + "forbidden": ["viscosity"] }, "Mushroom": { "minScore": 1300, - "required": [ - "streak_shots" - ], - "forbidden": [ - "base_combo" - ] + "required": ["streak_shots"], + "forbidden": ["base_combo"] }, "Tulip": { "minScore": 1400, - "required": [ - "viscosity" - ], - "forbidden": [ - "left_is_lava" - ] + "required": ["viscosity"], + "forbidden": ["left_is_lava"] }, "Chain": { "minScore": 1500, - "required": [ - "left_is_lava" - ], - "forbidden": [ - "right_is_lava" - ] + "required": ["left_is_lava"], + "forbidden": ["right_is_lava"] }, "Marion": { "minScore": 1600, - "required": [ - "viscosity" - ], - "forbidden": [ - "left_is_lava" - ] + "required": ["viscosity"], + "forbidden": ["left_is_lava"] }, "Renan": { "minScore": 1700, - "required": [ - "viscosity" - ], - "forbidden": [ - "skip_last" - ] + "required": ["viscosity"], + "forbidden": ["skip_last"] }, "Violet Pairs": { "minScore": 1800, - "required": [ - "skip_last" - ], - "forbidden": [ - "base_combo" - ] + "required": ["skip_last"], + "forbidden": ["base_combo"] }, "Red Cups": { "minScore": 1900, - "required": [ - "skip_last" - ], - "forbidden": [ - "viscosity" - ] + "required": ["skip_last"], + "forbidden": ["viscosity"] }, "Cactus": { "minScore": 2000, - "required": [ - "right_is_lava" - ], - "forbidden": [ - "skip_last" - ] + "required": ["right_is_lava"], + "forbidden": ["skip_last"] }, "Sunny Face": { "minScore": 2100, - "required": [ - "streak_shots", - "base_combo" - ], - "forbidden": [ - "smaller_puck", - "skip_last" - ] + "required": ["streak_shots", "base_combo"], + "forbidden": ["smaller_puck", "skip_last"] }, "Mountain": { "minScore": 2200, - "required": [ - "smaller_puck", - "streak_shots" - ], - "forbidden": [ - "left_is_lava", - "skip_last" - ] + "required": ["smaller_puck", "streak_shots"], + "forbidden": ["left_is_lava", "skip_last"] }, "Dollar": { "minScore": 2300, - "required": [ - "pierce", - "smaller_puck" - ], - "forbidden": [ - "left_is_lava", - "base_combo" - ] + "required": ["pierce", "smaller_puck"], + "forbidden": ["left_is_lava", "base_combo"] }, "Waves": { "minScore": 2400, - "required": [ - "left_is_lava", - "smaller_puck" - ], - "forbidden": [ - "picky_eater", - "pierce" - ] + "required": ["left_is_lava", "smaller_puck"], + "forbidden": ["picky_eater", "pierce"] }, "Box": { "minScore": 2500, - "required": [ - "left_is_lava", - "picky_eater" - ], - "forbidden": [ - "smaller_puck", - "base_combo" - ] + "required": ["left_is_lava", "picky_eater"], + "forbidden": ["smaller_puck", "base_combo"] }, "Rose": { "minScore": 2600, - "required": [ - "compound_interest", - "picky_eater" - ], - "forbidden": [ - "left_is_lava", - "base_combo" - ] + "required": ["compound_interest", "picky_eater"], + "forbidden": ["left_is_lava", "base_combo"] }, "Time": { "minScore": 2700, - "required": [ - "picky_eater", - "right_is_lava" - ], - "forbidden": [ - "pierce", - "left_is_lava" - ] + "required": ["picky_eater", "right_is_lava"], + "forbidden": ["pierce", "left_is_lava"] }, "Watermelon": { "minScore": 2800, - "required": [ - "hot_start", - "base_combo" - ], - "forbidden": [ - "pierce", - "right_is_lava" - ] + "required": ["hot_start", "base_combo"], + "forbidden": ["pierce", "right_is_lava"] }, "Worms": { "minScore": 2900, - "required": [ - "picky_eater", - "hot_start" - ], - "forbidden": [ - "right_is_lava", - "pierce" - ] + "required": ["picky_eater", "hot_start"], + "forbidden": ["right_is_lava", "pierce"] }, "Ocean Sunrise": { "minScore": 3000, - "required": [ - "smaller_puck", - "hot_start" - ], - "forbidden": [ - "streak_shots", - "telekinesis" - ] + "required": ["smaller_puck", "hot_start"], + "forbidden": ["streak_shots", "telekinesis"] }, "Crosses": { "minScore": 3100, - "required": [ - "pierce", - "sapper" - ], - "forbidden": [ - "smaller_puck", - "compound_interest" - ] + "required": ["pierce", "sapper"], + "forbidden": ["smaller_puck", "compound_interest"] }, "Negative space": { "minScore": 3200, - "required": [ - "left_is_lava", - "smaller_puck" - ], - "forbidden": [ - "right_is_lava", - "hot_start" - ] + "required": ["left_is_lava", "smaller_puck"], + "forbidden": ["right_is_lava", "hot_start"] }, "UK": { "minScore": 3300, - "required": [ - "right_is_lava", - "left_is_lava" - ], - "forbidden": [ - "base_combo", - "smaller_puck" - ] + "required": ["right_is_lava", "left_is_lava"], + "forbidden": ["base_combo", "smaller_puck"] }, "Greece": { "minScore": 3400, - "required": [ - "left_is_lava", - "right_is_lava" - ], - "forbidden": [ - "telekinesis", - "hot_start" - ] + "required": ["left_is_lava", "right_is_lava"], + "forbidden": ["telekinesis", "hot_start"] }, "Russia": { "minScore": 3500, - "required": [ - "compound_interest", - "bigger_explosions" - ], - "forbidden": [ - "sapper", - "pierce" - ] + "required": ["compound_interest", "bigger_explosions"], + "forbidden": ["sapper", "pierce"] }, "Ukraine": { "minScore": 3600, - "required": [ - "pierce", - "sapper" - ], - "forbidden": [ - "base_combo", - "bigger_explosions" - ] + "required": ["pierce", "sapper"], + "forbidden": ["base_combo", "bigger_explosions"] }, "Poland": { "minScore": 3700, - "required": [ - "viscosity", - "picky_eater" - ], - "forbidden": [ - "skip_last", - "pierce" - ] + "required": ["viscosity", "picky_eater"], + "forbidden": ["skip_last", "pierce"] }, "Yellow 71": { "minScore": 3800, - "required": [ - "base_combo", - "viscosity" - ], - "forbidden": [ - "picky_eater", - "skip_last" - ] + "required": ["base_combo", "viscosity"], + "forbidden": ["picky_eater", "skip_last"] }, "71 on white": { "minScore": 3900, - "required": [ - "viscosity", - "picky_eater" - ], - "forbidden": [ - "compound_interest", - "skip_last" - ] + "required": ["viscosity", "picky_eater"], + "forbidden": ["compound_interest", "skip_last"] }, "Blue 71": { "minScore": 4000, - "required": [ - "compound_interest", - "pierce_color" - ], - "forbidden": [ - "left_is_lava", - "viscosity" - ] + "required": ["compound_interest", "pierce_color"], + "forbidden": ["left_is_lava", "viscosity"] }, "Seventy one": { "minScore": 4100, - "required": [ - "viscosity", - "base_combo" - ], - "forbidden": [ - "left_is_lava", - "pierce_color" - ] + "required": ["viscosity", "base_combo"], + "forbidden": ["left_is_lava", "pierce_color"] }, "B71": { "minScore": 4200, - "required": [ - "skip_last", - "viscosity" - ], - "forbidden": [ - "telekinesis", - "left_is_lava" - ] + "required": ["skip_last", "viscosity"], + "forbidden": ["telekinesis", "left_is_lava"] }, "Pig": { "minScore": 4300, - "required": [ - "skip_last", - "viscosity" - ], - "forbidden": [ - "ball_repulse_ball", - "telekinesis" - ] + "required": ["skip_last", "viscosity"], + "forbidden": ["ball_repulse_ball", "telekinesis"] }, "Big Pig": { "minScore": 4400, - "required": [ - "pierce", - "sapper" - ], - "forbidden": [ - "skip_last", - "compound_interest" - ] + "required": ["pierce", "sapper"], + "forbidden": ["skip_last", "compound_interest"] }, "Donkey Kong": { "minScore": 4500, - "required": [ - "ball_attract_ball", - "right_is_lava" - ], - "forbidden": [ - "bigger_explosions", - "skip_last" - ] + "required": ["ball_attract_ball", "right_is_lava"], + "forbidden": ["bigger_explosions", "skip_last"] }, "Banana": { "minScore": 4600, - "required": [ - "right_is_lava", - "soft_reset" - ], - "forbidden": [ - "base_combo", - "skip_last" - ] + "required": ["right_is_lava", "soft_reset"], + "forbidden": ["base_combo", "skip_last"] }, "Fox": { "minScore": 4700, - "required": [ - "ball_repulse_ball", - "puck_repulse_ball" - ], - "forbidden": [ - "right_is_lava", - "skip_last" - ] + "required": ["ball_repulse_ball", "puck_repulse_ball"], + "forbidden": ["right_is_lava", "skip_last"] }, "Wiki": { "minScore": 4800, - "required": [ - "base_combo", - "sapper" - ], - "forbidden": [ - "compound_interest", - "pierce" - ] + "required": ["base_combo", "sapper"], + "forbidden": ["compound_interest", "pierce"] }, "Baby Dog": { "minScore": 4900, - "required": [ - "bigger_explosions", - "pierce" - ], - "forbidden": [ - "sapper", - "compound_interest" - ] + "required": ["bigger_explosions", "pierce"], + "forbidden": ["sapper", "compound_interest"] }, "dog 21": { "minScore": 5000, - "required": [ - "ball_attract_ball", - "respawn" - ], - "forbidden": [ - "telekinesis", - "right_is_lava" - ] + "required": ["ball_attract_ball", "respawn"], + "forbidden": ["telekinesis", "right_is_lava"] }, "A": { "minScore": 5100, - "required": [ - "telekinesis", - "base_combo", - "sturdy_bricks" - ], - "forbidden": [ - "hot_start", - "top_is_lava", - "bigger_puck" - ] + "required": ["telekinesis", "base_combo", "sturdy_bricks"], + "forbidden": ["hot_start", "top_is_lava", "bigger_puck"] }, "B": { "minScore": 5200, - "required": [ - "pierce", - "hot_start", - "telekinesis" - ], - "forbidden": [ - "sapper", - "ball_repulse_ball", - "puck_repulse_ball" - ] + "required": ["pierce", "hot_start", "telekinesis"], + "forbidden": ["sapper", "ball_repulse_ball", "puck_repulse_ball"] }, "C": { "minScore": 5300, - "required": [ - "hot_start", - "telekinesis", - "compound_interest" - ], - "forbidden": [ - "top_is_lava", - "bigger_puck", - "bigger_explosions" - ] + "required": ["hot_start", "telekinesis", "compound_interest"], + "forbidden": ["top_is_lava", "bigger_puck", "bigger_explosions"] }, "D": { "minScore": 5400, - "required": [ - "hot_start", - "bigger_explosions", - "ball_attract_ball" - ], - "forbidden": [ - "telekinesis", - "soft_reset", - "compound_interest" - ] + "required": ["hot_start", "bigger_explosions", "ball_attract_ball"], + "forbidden": ["telekinesis", "soft_reset", "compound_interest"] }, "e": { "minScore": 5500, - "required": [ - "respawn", - "hot_start", - "telekinesis" - ], - "forbidden": [ - "ball_attract_ball", - "top_is_lava", - "bigger_puck" - ] + "required": ["respawn", "hot_start", "telekinesis"], + "forbidden": ["ball_attract_ball", "top_is_lava", "bigger_puck"] }, "Elephant": { "minScore": 5600, - "required": [ - "ball_repulse_ball", - "puck_repulse_ball", - "soft_reset" - ], - "forbidden": [ - "base_combo", - "sapper", - "telekinesis" - ] + "required": ["ball_repulse_ball", "puck_repulse_ball", "soft_reset"], + "forbidden": ["base_combo", "sapper", "telekinesis"] }, "Orca": { "minScore": 5700, - "required": [ - "pierce", - "sapper", - "respawn" - ], - "forbidden": [ - "concave_puck", - "telekinesis", - "compound_interest" - ] + "required": ["pierce", "sapper", "respawn"], + "forbidden": ["concave_puck", "telekinesis", "compound_interest"] }, "Shark": { "minScore": 5800, - "required": [ - "bigger_explosions", - "compound_interest", - "base_combo" - ], - "forbidden": [ - "right_is_lava", - "concave_puck", - "ball_attract_ball" - ] + "required": ["bigger_explosions", "compound_interest", "base_combo"], + "forbidden": ["right_is_lava", "concave_puck", "ball_attract_ball"] }, "Bird": { "minScore": 5900, - "required": [ - "right_is_lava", - "concave_puck", - "sturdy_bricks" - ], - "forbidden": [ - "ball_attract_ball", - "streak_shots", - "soft_reset" - ] + "required": ["right_is_lava", "concave_puck", "sturdy_bricks"], + "forbidden": ["ball_attract_ball", "streak_shots", "soft_reset"] }, "Tux": { "minScore": 6000, - "required": [ - "pierce", - "coin_magnet", - "bigger_puck" - ], - "forbidden": [ - "sapper", - "top_is_lava", - "helium" - ] + "required": ["pierce", "coin_magnet", "bigger_puck"], + "forbidden": ["sapper", "top_is_lava", "helium"] }, "Armenia": { "minScore": 6100, - "required": [ - "top_is_lava", - "respawn", - "bigger_puck" - ], - "forbidden": [ - "base_combo", - "coin_magnet", - "ball_repulse_ball" - ] + "required": ["top_is_lava", "respawn", "bigger_puck"], + "forbidden": ["base_combo", "coin_magnet", "ball_repulse_ball"] }, "Austria": { "minScore": 6200, - "required": [ - "top_is_lava", - "telekinesis", - "bigger_puck" - ], - "forbidden": [ - "coin_magnet", - "viscosity", - "unbounded" - ] + "required": ["top_is_lava", "telekinesis", "bigger_puck"], + "forbidden": ["coin_magnet", "viscosity", "unbounded"] }, "Benin": { "minScore": 6300, - "required": [ - "telekinesis", - "right_is_lava", - "bigger_explosions" - ], - "forbidden": [ - "viscosity", - "top_is_lava", - "unbounded" - ] + "required": ["telekinesis", "right_is_lava", "bigger_explosions"], + "forbidden": ["viscosity", "top_is_lava", "unbounded"] }, "Botswana": { "minScore": 6400, - "required": [ - "viscosity", - "telekinesis", - "unbounded" - ], - "forbidden": [ - "sturdy_bricks", - "soft_reset", - "right_is_lava" - ] + "required": ["viscosity", "telekinesis", "unbounded"], + "forbidden": ["sturdy_bricks", "soft_reset", "right_is_lava"] }, "Bulgaria": { "minScore": 6500, - "required": [ - "helium", - "puck_repulse_ball", - "unbounded" - ], - "forbidden": [ - "ball_repulse_ball", - "viscosity", - "pierce" - ] + "required": ["helium", "puck_repulse_ball", "unbounded"], + "forbidden": ["ball_repulse_ball", "viscosity", "pierce"] }, "Canada": { "minScore": 6600, - "required": [ - "skip_last", - "respawn", - "base_combo" - ], - "forbidden": [ - "asceticism", - "unbounded", - "telekinesis" - ] + "required": ["skip_last", "respawn", "base_combo"], + "forbidden": ["asceticism", "unbounded", "telekinesis"] }, "Chad": { "minScore": 6700, - "required": [ - "compound_interest", - "bigger_explosions", - "skip_last" - ], - "forbidden": [ - "concave_puck", - "streak_shots", - "telekinesis" - ] + "required": ["compound_interest", "bigger_explosions", "skip_last"], + "forbidden": ["concave_puck", "streak_shots", "telekinesis"] }, "China": { "minScore": 6800, - "required": [ - "nbricks", - "concave_puck", - "streak_shots" - ], - "forbidden": [ - "ball_attract_ball", - "skip_last", - "base_combo" - ] + "required": ["nbricks", "concave_puck", "streak_shots"], + "forbidden": ["ball_attract_ball", "skip_last", "base_combo"] }, "Colombia": { "minScore": 6900, - "required": [ - "streak_shots", - "smaller_puck", - "concave_puck" - ], - "forbidden": [ - "puck_repulse_ball", - "ball_repulse_ball", - "sapper" - ] + "required": ["streak_shots", "smaller_puck", "concave_puck"], + "forbidden": ["puck_repulse_ball", "ball_repulse_ball", "sapper"] }, "Republic of the Congo": { "minScore": 7000, - "required": [ - "ball_repulse_ball", - "puck_repulse_ball", - "coin_magnet" - ], - "forbidden": [ - "bigger_puck", - "top_is_lava", - "skip_last" - ] + "required": ["ball_repulse_ball", "puck_repulse_ball", "coin_magnet"], + "forbidden": ["bigger_puck", "top_is_lava", "skip_last"] }, "Côte d'Ivoire": { "minScore": 7100, - "required": [ - "coin_magnet", - "bigger_puck", - "top_is_lava" - ], - "forbidden": [ - "base_combo", - "etherealcoins", - "telekinesis" - ] + "required": ["coin_magnet", "bigger_puck", "top_is_lava"], + "forbidden": ["base_combo", "etherealcoins", "telekinesis"] }, "Denmark": { "minScore": 7200, - "required": [ - "bigger_explosions", - "coin_magnet", - "etherealcoins" - ], - "forbidden": [ - "respawn", - "bigger_puck", - "top_is_lava" - ] + "required": ["bigger_explosions", "coin_magnet", "etherealcoins"], + "forbidden": ["respawn", "bigger_puck", "top_is_lava"] }, "El Salvador": { "minScore": 7300, - "required": [ - "bigger_puck", - "top_is_lava", - "helium" - ], - "forbidden": [ - "pierce", - "coin_magnet", - "sapper" - ] + "required": ["bigger_puck", "top_is_lava", "helium"], + "forbidden": ["pierce", "coin_magnet", "sapper"] }, "Egypt": { "minScore": 7400, - "required": [ - "zen", - "top_is_lava", - "soft_reset" - ], - "forbidden": [ - "bigger_puck", - "telekinesis", - "puck_repulse_ball" - ] + "required": ["zen", "top_is_lava", "soft_reset"], + "forbidden": ["bigger_puck", "telekinesis", "puck_repulse_ball"] }, "Estonia": { "minScore": 7500, - "required": [ - "zen", - "telekinesis", - "hot_start" - ], - "forbidden": [ - "top_is_lava", - "bigger_puck", - "concave_puck" - ] + "required": ["zen", "telekinesis", "hot_start"], + "forbidden": ["top_is_lava", "bigger_puck", "concave_puck"] }, "Finland": { "minScore": 7600, - "required": [ - "concave_puck", - "hot_start", - "telekinesis" - ], - "forbidden": [ - "zen", - "compound_interest", - "base_combo" - ] + "required": ["concave_puck", "hot_start", "telekinesis"], + "forbidden": ["zen", "compound_interest", "base_combo"] }, "Gabon": { "minScore": 7700, - "required": [ - "respawn", - "ball_attract_ball", - "zen" - ], - "forbidden": [ - "streak_shots", - "sturdy_bricks", - "hot_start" - ] + "required": ["respawn", "ball_attract_ball", "zen"], + "forbidden": ["streak_shots", "sturdy_bricks", "hot_start"] }, "Georgia": { "minScore": 7800, - "required": [ - "helium", - "zen", - "smaller_puck" - ], - "forbidden": [ - "pierce", - "telekinesis", - "sapper" - ] + "required": ["helium", "zen", "smaller_puck"], + "forbidden": ["pierce", "telekinesis", "sapper"] }, "Guinea": { "minScore": 7900, - "required": [ - "zen", - "nbricks", - "smaller_puck" - ], - "forbidden": [ - "pierce_color", - "left_is_lava", - "ball_repulse_ball" - ] + "required": ["zen", "nbricks", "smaller_puck"], + "forbidden": ["pierce_color", "left_is_lava", "ball_repulse_ball"] }, "Indonesia": { "minScore": 8000, - "required": [ - "trampoline", - "zen", - "right_is_lava" - ], - "forbidden": [ - "nbricks", - "coin_magnet", - "hot_start" - ] + "required": ["trampoline", "zen", "right_is_lava"], + "forbidden": ["nbricks", "coin_magnet", "hot_start"] }, "Pingwin": { "minScore": 8100, - "required": [ - "zen", - "compound_interest", - "pierce" - ], - "forbidden": [ - "right_is_lava", - "sturdy_bricks", - "helium" - ] + "required": ["zen", "compound_interest", "pierce"], + "forbidden": ["right_is_lava", "sturdy_bricks", "helium"] }, "Dog 8": { "minScore": 8200, - "required": [ - "zen", - "ball_attract_ball", - "coin_magnet" - ], - "forbidden": [ - "sacrifice", - "sturdy_bricks", - "bigger_puck" - ] + "required": ["zen", "ball_attract_ball", "coin_magnet"], + "forbidden": ["sacrifice", "sturdy_bricks", "bigger_puck"] }, "Sunglasses": { "minScore": 8300, - "required": [ - "zen", - "sacrifice", - "coin_magnet" - ], - "forbidden": [ - "respawn", - "bigger_puck", - "top_is_lava" - ] + "required": ["zen", "sacrifice", "coin_magnet"], + "forbidden": ["respawn", "bigger_puck", "top_is_lava"] }, "Balloon": { "minScore": 8400, - "required": [ - "soft_reset", - "coin_magnet", - "zen" - ], - "forbidden": [ - "concave_puck", - "sacrifice", - "bigger_puck" - ] + "required": ["soft_reset", "coin_magnet", "zen"], + "forbidden": ["concave_puck", "sacrifice", "bigger_puck"] }, "Opening": { "minScore": 8500, - "required": [ - "streak_shots", - "bigger_puck", - "top_is_lava" - ], - "forbidden": [ - "zen", - "etherealcoins", - "coin_magnet" - ] + "required": ["streak_shots", "bigger_puck", "top_is_lava"], + "forbidden": ["zen", "etherealcoins", "coin_magnet"] }, "Stripes": { "minScore": 8600, - "required": [ - "helium", - "base_combo", - "zen" - ], - "forbidden": [ - "top_is_lava", - "ball_attract_ball", - "bigger_puck" - ] + "required": ["helium", "base_combo", "zen"], + "forbidden": ["top_is_lava", "ball_attract_ball", "bigger_puck"] }, "You are here": { "minScore": 8700, - "required": [ - "zen", - "forgiving", - "telekinesis" - ], - "forbidden": [ - "smaller_puck", - "viscosity", - "top_is_lava" - ] + "required": ["zen", "forgiving", "telekinesis"], + "forbidden": ["smaller_puck", "viscosity", "top_is_lava"] }, "Gear": { "minScore": 8800, - "required": [ - "pierce_color", - "telekinesis", - "left_is_lava" - ], - "forbidden": [ - "unbounded", - "respawn", - "zen" - ] + "required": ["pierce_color", "telekinesis", "left_is_lava"], + "forbidden": ["unbounded", "respawn", "zen"] }, "Play": { "minScore": 8900, - "required": [ - "zen", - "right_is_lava", - "skip_last" - ], - "forbidden": [ - "ball_attracts_coins", - "telekinesis", - "unbounded" - ] + "required": ["zen", "right_is_lava", "skip_last"], + "forbidden": ["ball_attracts_coins", "telekinesis", "unbounded"] }, "City": { "minScore": 9000, - "required": [ - "passive_income", - "asceticism", - "soft_reset" - ], - "forbidden": [ - "hot_start", - "ball_repulse_ball", - "base_combo" - ] + "required": ["passive_income", "asceticism", "soft_reset"], + "forbidden": ["hot_start", "ball_repulse_ball", "base_combo"] }, "Wiggle": { "minScore": 9100, - "required": [ - "right_is_lava", - "trampoline", - "ball_attracts_coins" - ], - "forbidden": [ - "sturdy_bricks", - "hot_start", - "compound_interest" - ] + "required": ["right_is_lava", "trampoline", "ball_attracts_coins"], + "forbidden": ["sturdy_bricks", "hot_start", "compound_interest"] }, "Graph": { "minScore": 9200, - "required": [ - "hot_start", - "shocks", - "sapper" - ], - "forbidden": [ - "pierce", - "ball_attract_ball", - "ball_attracts_coins" - ] + "required": ["hot_start", "shocks", "sapper"], + "forbidden": ["pierce", "ball_attract_ball", "ball_attracts_coins"] }, "Lightbulb": { "minScore": 9300, - "required": [ - "hot_start", - "passive_income", - "helium" - ], - "forbidden": [ - "trampoline", - "ball_attracts_coins", - "pierce" - ] + "required": ["hot_start", "passive_income", "helium"], + "forbidden": ["trampoline", "ball_attracts_coins", "pierce"] }, "Note": { "minScore": 9400, - "required": [ - "ball_repulse_ball", - "puck_repulse_ball", - "nbricks" - ], - "forbidden": [ - "hot_start", - "respawn", - "etherealcoins" - ] + "required": ["ball_repulse_ball", "puck_repulse_ball", "nbricks"], + "forbidden": ["hot_start", "respawn", "etherealcoins"] }, "Rocket": { "minScore": 9500, - "required": [ - "etherealcoins", - "soft_reset", - "asceticism" - ], - "forbidden": [ - "coin_magnet", - "hot_start", - "bigger_puck" - ] + "required": ["etherealcoins", "soft_reset", "asceticism"], + "forbidden": ["coin_magnet", "hot_start", "bigger_puck"] }, "Abstract": { "minScore": 9600, - "required": [ - "bigger_explosions", - "compound_interest", - "etherealcoins" - ], - "forbidden": [ - "coin_magnet", - "passive_income", - "nbricks" - ] + "required": ["bigger_explosions", "compound_interest", "etherealcoins"], + "forbidden": ["coin_magnet", "passive_income", "nbricks"] }, "Fingerprint": { "minScore": 9700, - "required": [ - "pierce", - "sapper", - "shocks" - ], - "forbidden": [ - "base_combo", - "implosions", - "helium" - ] + "required": ["pierce", "sapper", "shocks"], + "forbidden": ["base_combo", "implosions", "helium"] }, "Leaf": { "minScore": 9800, - "required": [ - "concave_puck", - "sacrifice", - "puck_repulse_ball" - ], - "forbidden": [ - "coin_magnet", - "trampoline", - "ball_repulse_ball" - ] + "required": ["concave_puck", "sacrifice", "puck_repulse_ball"], + "forbidden": ["coin_magnet", "trampoline", "ball_repulse_ball"] }, "Abstract 2": { "minScore": 9900, - "required": [ - "coin_magnet", - "streak_shots", - "sacrifice" - ], - "forbidden": [ - "bigger_puck", - "top_is_lava", - "right_is_lava" - ] + "required": ["coin_magnet", "streak_shots", "sacrifice"], + "forbidden": ["bigger_puck", "top_is_lava", "right_is_lava"] }, "Abstract 3": { "minScore": 10000, - "required": [ - "sacrifice", - "nbricks", - "etherealcoins" - ], - "forbidden": [ - "shocks", - "sapper", - "asceticism" - ] + "required": ["sacrifice", "nbricks", "etherealcoins"], + "forbidden": ["shocks", "sapper", "asceticism"] }, "Abstract 4": { "minScore": 10100, - "required": [ - "trampoline", - "bigger_explosions", - "sacrifice" - ], - "forbidden": [ - "ball_attracts_coins", - "ghost_coins", - "ball_attract_ball" - ] + "required": ["trampoline", "bigger_explosions", "sacrifice"], + "forbidden": ["ball_attracts_coins", "ghost_coins", "ball_attract_ball"] }, "Abstract 5": { "minScore": 10200, - "required": [ - "ball_attracts_coins", - "implosions", - "forgiving" - ], - "forbidden": [ - "viscosity", - "base_combo", - "unbounded" - ] + "required": ["ball_attracts_coins", "implosions", "forgiving"], + "forbidden": ["viscosity", "base_combo", "unbounded"] }, "Abstract 6": { "minScore": 10300, - "required": [ - "puck_repulse_ball", - "ball_repulse_ball", - "forgiving" - ], - "forbidden": [ - "viscosity", - "unbounded", - "passive_income" - ] + "required": ["puck_repulse_ball", "ball_repulse_ball", "forgiving"], + "forbidden": ["viscosity", "unbounded", "passive_income"] }, "Hemiola": { "minScore": 10400, - "required": [ - "limitless", - "unbounded", - "viscosity" - ], - "forbidden": [ - "right_is_lava", - "forgiving", - "sturdy_bricks" - ] + "required": ["limitless", "unbounded", "viscosity"], + "forbidden": ["right_is_lava", "forgiving", "sturdy_bricks"] }, "Obigre": { "minScore": 10500, - "required": [ - "sapper", - "shocks", - "soft_reset" - ], - "forbidden": [ - "bigger_explosions", - "pierce", - "skip_last" - ] + "required": ["sapper", "shocks", "soft_reset"], + "forbidden": ["bigger_explosions", "pierce", "skip_last"] }, "Noodlemire": { "minScore": 10600, - "required": [ - "skip_last", - "concave_puck", - "passive_income" - ], - "forbidden": [ - "ball_attract_ball", - "side_flip", - "side_kick" - ] + "required": ["skip_last", "concave_puck", "passive_income"], + "forbidden": ["ball_attract_ball", "side_flip", "side_kick"] }, "Bearded axe": { "minScore": 10700, - "required": [ - "base_combo", - "streak_shots", - "side_flip" - ], - "forbidden": [ - "side_kick", - "implosions", - "concave_puck" - ] + "required": ["base_combo", "streak_shots", "side_flip"], + "forbidden": ["side_kick", "implosions", "concave_puck"] }, "Lebanon": { "minScore": 10800, - "required": [ - "side_kick", - "side_flip", - "etherealcoins" - ], - "forbidden": [ - "smaller_puck", - "streak_shots", - "trampoline" - ] + "required": ["side_kick", "side_flip", "etherealcoins"], + "forbidden": ["smaller_puck", "streak_shots", "trampoline"] }, "Spain": { "minScore": 10900, - "required": [ - "smaller_puck", - "passive_income", - "compound_interest" - ], - "forbidden": [ - "fountain_toss", - "side_kick", - "side_flip" - ] + "required": ["smaller_puck", "passive_income", "compound_interest"], + "forbidden": ["fountain_toss", "side_kick", "side_flip"] }, "Uzbekistan": { "minScore": 11000, - "required": [ - "picky_eater", - "ghost_coins", - "bigger_explosions" - ], - "forbidden": [ - "base_combo", - "clairvoyant", - "implosions" - ] + "required": ["picky_eater", "ghost_coins", "bigger_explosions"], + "forbidden": ["base_combo", "clairvoyant", "implosions"] }, "Pakistan": { "minScore": 11100, - "required": [ - "nbricks", - "ghost_coins", - "trampoline" - ], - "forbidden": [ - "picky_eater", - "clairvoyant", - "corner_shot" - ] + "required": ["nbricks", "ghost_coins", "trampoline"], + "forbidden": ["picky_eater", "clairvoyant", "corner_shot"] }, "Korea": { "minScore": 11200, @@ -1324,282 +616,111 @@ "ball_attracts_coins", "ball_repulse_ball" ], - "forbidden": [ - "ghost_coins", - "picky_eater", - "etherealcoins" - ] + "forbidden": ["ghost_coins", "picky_eater", "etherealcoins"] }, "Chile": { "minScore": 11300, - "required": [ - "shocks", - "sapper", - "pierce" - ], - "forbidden": [ - "etherealcoins", - "ball_attracts_coins", - "ghost_coins" - ] + "required": ["shocks", "sapper", "pierce"], + "forbidden": ["etherealcoins", "ball_attracts_coins", "ghost_coins"] }, "Türkiye": { "minScore": 11400, - "required": [ - "compound_interest", - "fountain_toss", - "concave_puck" - ], - "forbidden": [ - "bigger_explosions", - "superhot", - "respawn" - ] + "required": ["compound_interest", "fountain_toss", "concave_puck"], + "forbidden": ["bigger_explosions", "superhot", "respawn"] }, "Taj Mahal": { "minScore": 11500, - "required": [ - "asceticism", - "soft_reset", - "streak_shots" - ], - "forbidden": [ - "concave_puck", - "ball_attract_ball", - "hot_start" - ] + "required": ["asceticism", "soft_reset", "streak_shots"], + "forbidden": ["concave_puck", "ball_attract_ball", "hot_start"] }, "Abstract 7": { "minScore": 11600, - "required": [ - "hot_start", - "nbricks", - "streak_shots" - ], - "forbidden": [ - "trampoline", - "smaller_puck", - "superhot" - ] + "required": ["hot_start", "nbricks", "streak_shots"], + "forbidden": ["trampoline", "smaller_puck", "superhot"] }, "Abstract 9": { "minScore": 11700, - "required": [ - "implosions", - "smaller_puck", - "right_is_lava" - ], - "forbidden": [ - "base_combo", - "sturdy_bricks", - "hot_start" - ] + "required": ["implosions", "smaller_puck", "right_is_lava"], + "forbidden": ["base_combo", "sturdy_bricks", "hot_start"] }, "Crosshair": { "minScore": 11800, - "required": [ - "pierce", - "pierce_color", - "left_is_lava" - ], - "forbidden": [ - "sapper", - "transparency", - "shocks" - ] + "required": ["pierce", "pierce_color", "left_is_lava"], + "forbidden": ["sapper", "transparency", "shocks"] }, "Abstract 10": { "minScore": 11900, - "required": [ - "transparency", - "ball_attract_ball", - "left_is_lava" - ], - "forbidden": [ - "pierce_color", - "rainbow", - "passive_income" - ] + "required": ["transparency", "ball_attract_ball", "left_is_lava"], + "forbidden": ["pierce_color", "rainbow", "passive_income"] }, "Face": { "minScore": 12000, - "required": [ - "rainbow", - "corner_shot", - "bricks_attract_coins" - ], - "forbidden": [ - "base_combo", - "clairvoyant", - "respawn" - ] + "required": ["rainbow", "corner_shot", "bricks_attract_coins"], + "forbidden": ["base_combo", "clairvoyant", "respawn"] }, "Eiffel tower": { "minScore": 12100, - "required": [ - "shocks", - "sapper", - "clairvoyant" - ], - "forbidden": [ - "passive_income", - "picky_eater", - "pierce" - ] + "required": ["shocks", "sapper", "clairvoyant"], + "forbidden": ["passive_income", "picky_eater", "pierce"] }, "Abstract 11": { "minScore": 12200, - "required": [ - "picky_eater", - "nbricks", - "addiction" - ], - "forbidden": [ - "minefield", - "sturdy_bricks", - "ghost_coins" - ] + "required": ["picky_eater", "nbricks", "addiction"], + "forbidden": ["minefield", "sturdy_bricks", "ghost_coins"] }, "Abstract 12": { "minScore": 12300, - "required": [ - "ghost_coins", - "sacrifice", - "ball_attracts_coins" - ], - "forbidden": [ - "concave_puck", - "picky_eater", - "compound_interest" - ] + "required": ["ghost_coins", "sacrifice", "ball_attracts_coins"], + "forbidden": ["concave_puck", "picky_eater", "compound_interest"] }, "Abstract 13": { "minScore": 12400, - "required": [ - "ball_attract_ball", - "streak_shots", - "ghost_coins" - ], - "forbidden": [ - "passive_income", - "sacrifice", - "picky_eater" - ] + "required": ["ball_attract_ball", "streak_shots", "ghost_coins"], + "forbidden": ["passive_income", "sacrifice", "picky_eater"] }, "Abstract 14": { "minScore": 12500, - "required": [ - "smaller_puck", - "asceticism", - "rainbow" - ], - "forbidden": [ - "bricks_attract_ball", - "soft_reset", - "respawn" - ] + "required": ["smaller_puck", "asceticism", "rainbow"], + "forbidden": ["bricks_attract_ball", "soft_reset", "respawn"] }, "S": { "minScore": 12600, - "required": [ - "pierce", - "sapper", - "shocks" - ], - "forbidden": [ - "etherealcoins", - "trampoline", - "pierce_color" - ] + "required": ["pierce", "sapper", "shocks"], + "forbidden": ["etherealcoins", "trampoline", "pierce_color"] }, "Abstract 15": { "minScore": 12700, - "required": [ - "forgiving", - "viscosity" - ], - "forbidden": [ - "fountain_toss", - "transparency", - "left_is_lava" - ] + "required": ["forgiving", "viscosity"], + "forbidden": ["fountain_toss", "transparency", "left_is_lava"] }, "Mario!": { "minScore": 12800, - "required": [ - "unbounded", - "limitless", - "viscosity" - ], - "forbidden": [ - "forgiving", - "skip_last", - "ball_attract_ball" - ] + "required": ["unbounded", "limitless", "viscosity"], + "forbidden": ["forgiving", "skip_last", "ball_attract_ball"] }, "Minesweeper": { "minScore": 12900, - "required": [ - "ottawa_treaty", - "skip_last", - "unbounded" - ], - "forbidden": [ - "limitless", - "viscosity", - "forgiving" - ] + "required": ["ottawa_treaty", "skip_last", "unbounded"], + "forbidden": ["limitless", "viscosity", "forgiving"] }, "Target": { "minScore": 13000, - "required": [ - "skip_last", - "implosions", - "base_combo" - ], - "forbidden": [ - "etherealcoins", - "reach", - "three_cushion" - ] + "required": ["skip_last", "implosions", "base_combo"], + "forbidden": ["etherealcoins", "reach", "three_cushion"] }, "The Boys": { "minScore": 13100, - "required": [ - "concave_puck", - "respawn", - "rainbow" - ], - "forbidden": [ - "reach", - "corner_shot", - "skip_last" - ] + "required": ["concave_puck", "respawn", "rainbow"], + "forbidden": ["reach", "corner_shot", "skip_last"] }, "A Very Dangerous High-Five": { "minScore": 13200, - "required": [ - "side_kick", - "side_flip", - "corner_shot" - ], - "forbidden": [ - "streak_shots", - "reach", - "clairvoyant" - ] + "required": ["side_kick", "rainbow", "corner_shot"], + "forbidden": ["streak_shots", "reach", "clairvoyant"] }, "Blinky": { - "required": [ - "clairvoyant", - "reach", - "double_or_nothing" - ], - "forbidden": [ - "nbricks", - "corner_shot", - "smaller_puck" - ], + "required": ["clairvoyant", "reach", "double_or_nothing"], + "forbidden": ["nbricks", "corner_shot", "smaller_puck"], "minScore": 13300 } -} \ No newline at end of file +} diff --git a/src/data/unlockConditions.test.ts b/src/data/unlockConditions.test.ts index 002c805..faa279c 100644 --- a/src/data/unlockConditions.test.ts +++ b/src/data/unlockConditions.test.ts @@ -1,38 +1,43 @@ -import conditions from "./unlockConditions.json" -import levels from "./levels.json" -import {rawUpgrades} from "../upgrades"; -import {getLevelUnlockCondition} from "../get_level_unlock_condition"; -import {UnlockCondition} from "../types"; +import conditions from "./unlockConditions.json"; +import levels from "./levels.json"; +import { rawUpgrades } from "../upgrades"; +import { getLevelUnlockCondition } from "../get_level_unlock_condition"; +import { UnlockCondition } from "../types"; describe("conditions", () => { - it("defines conditions for existing levels only", () => { - const conditionForMissingLevel=Object.keys(conditions).filter(levelName=>!levels.find(l=>l.name===levelName)) - expect(conditionForMissingLevel).toEqual([]); - }); - it("defines conditions with existing upgrades only", () => { - - const existingIds :Set= new Set(rawUpgrades.map(u=>u.id)); - const missing:Set=new Set(); - Object.values(conditions).forEach(({required,forbidden})=>{ - [...required,...forbidden].forEach(id=> { - if(!existingIds.has(id)) - missing.add(id) - }) - }) - - expect([...missing]).toEqual([]); + it("defines conditions for existing levels only", () => { + const conditionForMissingLevel = Object.keys(conditions).filter( + (levelName) => !levels.find((l) => l.name === levelName), + ); + expect(conditionForMissingLevel).toEqual([]); + }); + it("defines conditions with existing upgrades only", () => { + const existingIds: Set = new Set(rawUpgrades.map((u) => u.id)); + const missing: Set = new Set(); + Object.values(conditions).forEach(({ required, forbidden }) => { + [...required, ...forbidden].forEach((id) => { + if (!existingIds.has(id)) missing.add(id); + }); }); - it("defines conditions for all levels", () => { - const toAdd : Record= {} - levels.filter(l=>!l.name.startsWith('icon:')).forEach((l,li)=> { - if(l.name in conditions) return - toAdd[l.name]= getLevelUnlockCondition(li, l.name) - }) - if(Object.keys(toAdd).length){ - console.debug('Missing hardcoded conditons\n\n'+ JSON.stringify(toAdd).slice(1,-1)+'\n\n') - } - expect(Object.keys(toAdd)).toEqual([]); - }); + expect([...missing]).toEqual([]); + }); -}) \ No newline at end of file + it("defines conditions for all levels", () => { + const toAdd: Record = {}; + levels + .filter((l) => !l.name.startsWith("icon:")) + .forEach((l, li) => { + if (l.name in conditions) return; + toAdd[l.name] = getLevelUnlockCondition(li, l.name); + }); + if (Object.keys(toAdd).length) { + console.debug( + "Missing hardcoded conditons\n\n" + + JSON.stringify(toAdd).slice(1, -1) + + "\n\n", + ); + } + expect(Object.keys(toAdd)).toEqual([]); + }); +}); diff --git a/src/data/version.json b/src/data/version.json index ad1c46b..9ed5d76 100644 --- a/src/data/version.json +++ b/src/data/version.json @@ -1 +1 @@ -"29092809" +"29095000" diff --git a/src/game.less b/src/game.less index a966a17..578bbe0 100644 --- a/src/game.less +++ b/src/game.less @@ -450,14 +450,12 @@ h2.histogram-title strong { user-select: none; opacity: 1; border: 1px solid white; - &.desktop{ - + &.desktop { max-width: 300px; - } - &.mobile{ - width: 95vw; - left:2.5vw; + &.mobile { + width: 95vw; + left: 2.5vw; } } diff --git a/src/game.ts b/src/game.ts index 3ea86d9..895c947 100644 --- a/src/game.ts +++ b/src/game.ts @@ -98,7 +98,7 @@ import { getNearestUnlockHTML, openScorePanel } from "./openScorePanel"; import { monitorLevelsUnlocks } from "./monitorLevelsUnlocks"; import { levelEditorMenuEntry } from "./levelEditor"; import { categories } from "./upgrades"; -import {reasonLevelIsLocked} from "./get_level_unlock_condition"; +import { reasonLevelIsLocked } from "./get_level_unlock_condition"; export async function play() { if (await applyFullScreenChoice()) return; diff --git a/src/gameOver.ts b/src/gameOver.ts index c0fb636..6db560a 100644 --- a/src/gameOver.ts +++ b/src/gameOver.ts @@ -6,7 +6,6 @@ import { currentLevelInfo, describeLevel, pickedUpgradesHTMl, - } from "./game_utils"; import { askForPersistentStorage, @@ -18,7 +17,10 @@ import { stopRecording } from "./recording"; import { asyncAlert } from "./asyncAlert"; import { editRawLevelList } from "./levelEditor"; import { openCreativeModePerksPicker } from "./creative"; -import {isLevelLocked, reasonLevelIsLocked} from "./get_level_unlock_condition"; +import { + isLevelLocked, + reasonLevelIsLocked, +} from "./get_level_unlock_condition"; export function addToTotalPlayTime(ms: number) { setSettingValue( @@ -140,7 +142,7 @@ export function getHistograms(gameState: GameState) { .map((l, li) => ({ li, l, - r: reasonLevelIsLocked(li,l.name, runsHistory, false)?.text, + r: reasonLevelIsLocked(li, l.name, runsHistory, false)?.text, })) .filter((l) => l.r); @@ -160,7 +162,7 @@ export function getHistograms(gameState: GameState) { }); const unlocked = locked.filter( - ({ li ,l}) => !isLevelLocked(li, l.name, runsHistory), + ({ li, l }) => !isLevelLocked(li, l.name, runsHistory), ); if (unlocked.length) { unlockedLevels = ` diff --git a/src/gameStateMutators.ts b/src/gameStateMutators.ts index 49a159a..7654bd3 100644 --- a/src/gameStateMutators.ts +++ b/src/gameStateMutators.ts @@ -1265,7 +1265,6 @@ export function gameStateTick( // If you dont have buoy, we directly declare the coin "lost" to make it clear resetCombo(gameState, coin.x, coin.y); } - } if ( @@ -1659,7 +1658,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) { speedLimitDampener += 3; ball.vx += - (gameState.puckPosition > ball.x ? 1 :-1) * + (gameState.puckPosition > ball.x ? 1 : -1) * frames * yoyoEffectRate(gameState, ball); } diff --git a/src/game_utils.ts b/src/game_utils.ts index 2cb0390..55e8b5c 100644 --- a/src/game_utils.ts +++ b/src/game_utils.ts @@ -1,9 +1,9 @@ -import {Ball, Coin, GameState, Level, PerkId, PerksMap,} from "./types"; -import {icons, upgrades} from "./loadGameData"; -import {t} from "./i18n/i18n"; -import {clamp} from "./pure_functions"; -import {getSettingValue, getTotalScore} from "./settings"; -import {isOptionOn} from "./options"; +import { Ball, Coin, GameState, Level, PerkId, PerksMap } from "./types"; +import { icons, upgrades } from "./loadGameData"; +import { t } from "./i18n/i18n"; +import { clamp } from "./pure_functions"; +import { getSettingValue, getTotalScore } from "./settings"; +import { isOptionOn } from "./options"; export function describeLevel(level: Level) { let bricks = 0, @@ -192,10 +192,13 @@ export function telekinesisEffectRate(gameState: GameState, ball: Ball) { } export function yoyoEffectRate(gameState: GameState, ball: Ball) { - if(ball.vy < 0) return 0 - if(!gameState.perks.yoyo) return 0 - return Math.abs(gameState.puckPosition - ball.x)/gameState.gameZoneWidth * gameState.perks.yoyo/2 - + if (ball.vy < 0) return 0; + if (!gameState.perks.yoyo) return 0; + return ( + ((Math.abs(gameState.puckPosition - ball.x) / gameState.gameZoneWidth) * + gameState.perks.yoyo) / + 2 + ); } export function findLast( diff --git a/src/get_level_unlock_condition.ts b/src/get_level_unlock_condition.ts index 22cbc28..6892c1b 100644 --- a/src/get_level_unlock_condition.ts +++ b/src/get_level_unlock_condition.ts @@ -1,113 +1,123 @@ -import {PerkId, RunHistoryItem, UnlockCondition} from "./types"; -import {upgrades} from "./loadGameData"; -import {hashCode} from "./getLevelBackground"; -import {t} from "./i18n/i18n"; +import { PerkId, RunHistoryItem, UnlockCondition } from "./types"; +import { upgrades } from "./loadGameData"; +import { hashCode } from "./getLevelBackground"; +import { t } from "./i18n/i18n"; -import _hardCodedCondition from './data/unlockConditions.json' +import _hardCodedCondition from "./data/unlockConditions.json"; -const hardCodedCondition = _hardCodedCondition as Record +const hardCodedCondition = _hardCodedCondition as Record< + string, + UnlockCondition +>; let excluded: Set; function isExcluded(id: PerkId) { - if (!excluded) { - excluded = new Set([ - "extra_levels", - "extra_life", - "one_more_choice", - "shunt", - "slow_down", - ]); - // Avoid excluding a perk that's needed for the required one - upgrades.forEach((u) => { - if (u.requires) excluded.add(u.requires); - }); - } - return excluded.has(id); + if (!excluded) { + excluded = new Set([ + "extra_levels", + "extra_life", + "one_more_choice", + "shunt", + "slow_down", + ]); + // Avoid excluding a perk that's needed for the required one + upgrades.forEach((u) => { + if (u.requires) excluded.add(u.requires); + }); + } + return excluded.has(id); } -export function getLevelUnlockCondition(levelIndex: number, levelName:string):UnlockCondition { +export function getLevelUnlockCondition( + levelIndex: number, + levelName: string, +): UnlockCondition { + if (hardCodedCondition[levelName]) return hardCodedCondition[levelName]; + const result: UnlockCondition = { + required: [], + forbidden: [], + minScore: Math.max(-1000 + 100 * levelIndex, 0), + }; - if(hardCodedCondition[levelName]) return hardCodedCondition[levelName] - const result :UnlockCondition = { - required:[], - forbidden:[], - minScore : Math.max(-1000 + 100 * levelIndex, 0) - } + if (levelIndex > 20) { + const possibletargets = [...upgrades] + .slice(0, Math.floor(levelIndex / 2)) + .filter((u) => !isExcluded(u.id)) + .sort((a, b) => hashCode(levelIndex + a.id) - hashCode(levelIndex + b.id)) + .map((u) => u.id); - if (levelIndex > 20) { - const possibletargets = [...upgrades] - .slice(0, Math.floor(levelIndex / 2)) - .filter((u) => !isExcluded(u.id)) - .sort( - (a, b) => hashCode(levelIndex + a.id) - hashCode(levelIndex + b.id), - ).map(u => u.id); - - const length = Math.min(3, Math.ceil(levelIndex / 30)); - result.required = possibletargets.slice(0, length); - result.forbidden = possibletargets.slice(length, length + length); - } - return result + const length = Math.min(3, Math.ceil(levelIndex / 30)); + result.required = possibletargets.slice(0, length); + result.forbidden = possibletargets.slice(length, length + length); + } + return result; } export function getBestScoreMatching( - history: RunHistoryItem[], - required: PerkId[] = [], - forbidden: PerkId[] = [], + history: RunHistoryItem[], + required: PerkId[] = [], + forbidden: PerkId[] = [], ) { - return Math.max( - 0, - ...history - .filter( - (r) => - !required.find((id) => !r?.perks?.[id]) && - !forbidden.find((id) => r?.perks?.[id]), - ) - .map((r) => r.score), - ); + return Math.max( + 0, + ...history + .filter( + (r) => + !required.find((id) => !r?.perks?.[id]) && + !forbidden.find((id) => r?.perks?.[id]), + ) + .map((r) => r.score), + ); } export function isLevelLocked( - levelIndex: number, - levelName:string, - history: RunHistoryItem[]){ - const {required, forbidden, minScore} = getLevelUnlockCondition(levelIndex, levelName); - return getBestScoreMatching(history, required, forbidden) < minScore - + levelIndex: number, + levelName: string, + history: RunHistoryItem[], +) { + const { required, forbidden, minScore } = getLevelUnlockCondition( + levelIndex, + levelName, + ); + return getBestScoreMatching(history, required, forbidden) < minScore; } export function reasonLevelIsLocked( - levelIndex: number,levelName:string, - history: RunHistoryItem[], - mentionBestScore: boolean, + levelIndex: number, + levelName: string, + history: RunHistoryItem[], + mentionBestScore: boolean, ): null | { reached: number; minScore: number; text: string } { - - const {required, forbidden, minScore} = getLevelUnlockCondition(levelIndex, levelName); - const reached = getBestScoreMatching(history, required, forbidden); - let reachedText = - reached && mentionBestScore ? t("unlocks.reached", {reached}) : ""; - if (reached >= minScore) { - return null; - } else if (!required.length && !forbidden.length) { - return { - reached, - minScore, - text: t("unlocks.minScore", {minScore}) + reachedText, - }; - } else { - return { - reached, - minScore, - text: - t("unlocks.minScoreWithPerks", { - minScore, - required: required.map((u) => upgradeName(u)).join(", "), - forbidden: forbidden.map((u) => upgradeName(u)).join(", "), - }) + reachedText, - }; - } + const { required, forbidden, minScore } = getLevelUnlockCondition( + levelIndex, + levelName, + ); + const reached = getBestScoreMatching(history, required, forbidden); + let reachedText = + reached && mentionBestScore ? t("unlocks.reached", { reached }) : ""; + if (reached >= minScore) { + return null; + } else if (!required.length && !forbidden.length) { + return { + reached, + minScore, + text: t("unlocks.minScore", { minScore }) + reachedText, + }; + } else { + return { + reached, + minScore, + text: + t("unlocks.minScoreWithPerks", { + minScore, + required: required.map((u) => upgradeName(u)).join(", "), + forbidden: forbidden.map((u) => upgradeName(u)).join(", "), + }) + reachedText, + }; + } } -export function upgradeName(id:PerkId){ - return upgrades.find(u=>u.id==id)!.name -} \ No newline at end of file +export function upgradeName(id: PerkId) { + return upgrades.find((u) => u.id == id)!.name; +} diff --git a/src/levelEditor.ts b/src/levelEditor.ts index c2aaa7a..5ac5dbb 100644 --- a/src/levelEditor.ts +++ b/src/levelEditor.ts @@ -14,7 +14,7 @@ import { MAX_LEVEL_SIZE, MIN_LEVEL_SIZE, } from "./pure_functions"; -import {toast} from "./toast"; +import { toast } from "./toast"; const palette = _palette as Palette; @@ -234,7 +234,7 @@ export async function editRawLevelList(nth: number, color = "W") { }); return; } - if (action === "copy" || action ==='show_code') { + if (action === "copy" || action === "show_code") { let text = "```\n[" + (level.name || "unnamed level")?.replace(/\[|\]/gi, " ") + @@ -249,21 +249,23 @@ export async function editRawLevelList(nth: number, color = "W") { "]\n```"; if (action === "copy") { - try{ - await navigator.clipboard.writeText(text); - toast(t('editor.editing.copied')) - }catch (e){ - if('message' in e) { - toast(e.message) + try { + await navigator.clipboard.writeText(text); + toast(t("editor.editing.copied")); + } catch (e) { + if ("message" in e) { + toast(e.message); } } - }else{ - await asyncAlert({ - title:t('editor.editing.show_code'), - content:[` + } else { + await asyncAlert({ + title: t("editor.editing.show_code"), + content: [ + `
${text}
- `] - }) + `, + ], + }); } // return } diff --git a/src/level_editor/levels_editor.tsx b/src/level_editor/levels_editor.tsx index c4c08d6..2db9d5c 100644 --- a/src/level_editor/levels_editor.tsx +++ b/src/level_editor/levels_editor.tsx @@ -1,4 +1,4 @@ -import { Palette, RawLevel } from "../types"; +import { Palette, RawLevel } from "../types"; import _palette from "../data/palette.json"; import { createRoot } from "react-dom/client"; import { useEffect, useState } from "react"; diff --git a/src/migrations.ts b/src/migrations.ts index 5b3fa02..0bc4fb1 100644 --- a/src/migrations.ts +++ b/src/migrations.ts @@ -4,7 +4,10 @@ import _appVersion from "./data/version.json"; import { generateSaveFileContent } from "./generateSaveFileContent"; import { allLevels } from "./loadGameData"; import { toast } from "./toast"; -import {isLevelLocked, reasonLevelIsLocked} from "./get_level_unlock_condition"; +import { + isLevelLocked, + reasonLevelIsLocked, +} from "./get_level_unlock_condition"; // The page will be reloaded if any migrations were run let migrationsRun = 0; @@ -128,7 +131,7 @@ migrate("set_breakout_71_unlocked_levels" + _appVersion, () => { ) as string[]; allLevels - .filter((l, li) => !isLevelLocked(li,l.name, runsHistory)) + .filter((l, li) => !isLevelLocked(li, l.name, runsHistory)) .forEach((l) => { if (!breakout_71_unlocked_levels.includes(l.name)) { breakout_71_unlocked_levels.push(l.name); diff --git a/src/monitorLevelsUnlocks.ts b/src/monitorLevelsUnlocks.ts index c861a1b..390c853 100644 --- a/src/monitorLevelsUnlocks.ts +++ b/src/monitorLevelsUnlocks.ts @@ -1,22 +1,22 @@ -import {GameState, PerkId} from "./types"; +import { GameState, PerkId } from "./types"; import { getSettingValue, setSettingValue } from "./settings"; import { allLevels, icons } from "./loadGameData"; import { t } from "./i18n/i18n"; import { toast } from "./toast"; import { schedulGameSound } from "./gameStateMutators"; -import {getLevelUnlockCondition} from "./get_level_unlock_condition"; +import { getLevelUnlockCondition } from "./get_level_unlock_condition"; let list: { minScore: number; forbidden: PerkId[]; required: PerkId[]; }[]; -let unlocked : Set |null = null +let unlocked: Set | null = null; export function monitorLevelsUnlocks(gameState: GameState) { - if(!unlocked){ - unlocked = new Set( + if (!unlocked) { + unlocked = new Set( getSettingValue("breakout_71_unlocked_levels", []) as string[], ); } diff --git a/src/newGameState.ts b/src/newGameState.ts index 5512a34..d4f0f8c 100644 --- a/src/newGameState.ts +++ b/src/newGameState.ts @@ -13,7 +13,10 @@ import { isOptionOn } from "./options"; import { getHistory } from "./gameOver"; import { getSettingValue, getTotalScore } from "./settings"; import { isBlackListedForStart, isStartingPerk } from "./startingPerks"; -import {isLevelLocked, reasonLevelIsLocked} from "./get_level_unlock_condition"; +import { + isLevelLocked, + reasonLevelIsLocked, +} from "./get_level_unlock_condition"; export function getRunLevels( params: RunParams, diff --git a/src/openScorePanel.ts b/src/openScorePanel.ts index a7dc8db..519155d 100644 --- a/src/openScorePanel.ts +++ b/src/openScorePanel.ts @@ -1,17 +1,17 @@ import { GameState } from "./types"; import { asyncAlert } from "./asyncAlert"; import { t } from "./i18n/i18n"; -import { - levelsListHTMl, - max_levels, - pickedUpgradesHTMl, -} from "./game_utils"; +import { levelsListHTMl, max_levels, pickedUpgradesHTMl } from "./game_utils"; import { getCreativeModeWarning, getHistory } from "./gameOver"; import { pause } from "./game"; import { allLevels, icons } from "./loadGameData"; import { firstWhere } from "./pure_functions"; import { getSettingValue, getTotalScore } from "./settings"; -import {getLevelUnlockCondition, reasonLevelIsLocked, upgradeName} from "./get_level_unlock_condition"; +import { + getLevelUnlockCondition, + reasonLevelIsLocked, + upgradeName, +} from "./get_level_unlock_condition"; export async function openScorePanel(gameState: GameState) { pause(true); @@ -41,10 +41,13 @@ export function getNearestUnlockHTML(gameState: GameState) { const unlocked = new Set(getSettingValue("breakout_71_unlocked_levels", [])); const firstUnlockable = firstWhere(allLevels, (l, li) => { if (unlocked.has(l.name)) return; - const reason = reasonLevelIsLocked(li, l.name, getHistory(), false); + const reason = reasonLevelIsLocked(li, l.name, getHistory(), false); if (!reason) return; - const { minScore, forbidden, required } = getLevelUnlockCondition(li, l.name); + const { minScore, forbidden, required } = getLevelUnlockCondition( + li, + l.name, + ); const missing = required.filter((id) => !gameState?.perks?.[id]); // we can't have a forbidden perk if (forbidden.find((id) => gameState?.perks?.[id])) { @@ -69,7 +72,9 @@ export function getNearestUnlockHTML(gameState: GameState) { if (!firstUnlockable) return ""; let missingPoints = Math.max(0, firstUnlockable.minScore - gameState.score); - let missingUpgrades = firstUnlockable.missing.map((id) => upgradeName(id)).join(", "); + let missingUpgrades = firstUnlockable.missing + .map((id) => upgradeName(id)) + .join(", "); const title = (missingUpgrades && diff --git a/src/options.ts b/src/options.ts index 75ad310..0f87b29 100644 --- a/src/options.ts +++ b/src/options.ts @@ -12,8 +12,10 @@ export const options = { help: t("settings.sounds_help"), }, "mobile-mode": { - default: window.innerHeight > window.innerWidth ||('ontouchstart' in window) || - (navigator.maxTouchPoints > 0) , + default: + window.innerHeight > window.innerWidth || + "ontouchstart" in window || + navigator.maxTouchPoints > 0, name: t("settings.mobile"), help: t("settings.mobile_help"), }, diff --git a/src/render.ts b/src/render.ts index 24619e1..be60403 100644 --- a/src/render.ts +++ b/src/render.ts @@ -19,7 +19,8 @@ import { isOptionOn } from "./options"; import { ballTransparency, catchRateBest, - catchRateGood, clamp, + catchRateGood, + clamp, coinsBoostedCombo, levelTimeBest, levelTimeGood, @@ -401,11 +402,14 @@ export function render(gameState: GameState) { ) { ctx.beginPath(); ctx.moveTo(gameState.puckPosition, gameState.gameZoneHeight); - ctx.globalAlpha =clamp( + ctx.globalAlpha = clamp( Math.max( telekinesisEffectRate(gameState, ball), yoyoEffectRate(gameState, ball), - ) * ballAlpha,0,1); + ) * ballAlpha, + 0, + 1, + ); ctx.strokeStyle = gameState.puckColor; ctx.bezierCurveTo( gameState.puckPosition, diff --git a/src/tooltip.ts b/src/tooltip.ts index a03d21a..65454ab 100644 --- a/src/tooltip.ts +++ b/src/tooltip.ts @@ -14,9 +14,9 @@ export function hideAnyTooltip() { const tooltip = document.getElementById("tooltip") as HTMLDivElement; function setupMobileTooltips(tooltip: HTMLDivElement) { - tooltip.className='mobile' + tooltip.className = "mobile"; function openTooltip(e: Event) { - hideAnyTooltip() + hideAnyTooltip(); const hovering = e.target as HTMLElement; if (!hovering?.hasAttribute("data-help-content")) { return; @@ -25,9 +25,8 @@ function setupMobileTooltips(tooltip: HTMLDivElement) { e.preventDefault(); tooltip.innerHTML = hovering.getAttribute("data-help-content") || ""; tooltip.style.display = ""; - const { top } = hovering.getBoundingClientRect(); + const { top } = hovering.getBoundingClientRect(); tooltip.style.transform = `translate(0,${top}px) translate(0,-100%)`; - } document.body.addEventListener("touchstart", openTooltip, true); @@ -62,7 +61,7 @@ function setupMobileTooltips(tooltip: HTMLDivElement) { } function setupDesktopTooltips(tooltip: HTMLDivElement) { - tooltip.className='desktop' + tooltip.className = "desktop"; function updateTooltipPosition(e: { clientX: number; clientY: number }) { tooltip.style.transform = `translate(${e.clientX}px,${e.clientY}px) translate(${e.clientX > window.innerWidth / 2 ? "-100%" : "0"},${e.clientY > (window.innerHeight * 2) / 3 ? "-100%" : "20px"})`; } diff --git a/src/types.d.ts b/src/types.d.ts index 4e666fa..c576fcd 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,5 +1,5 @@ -import {rawUpgrades} from "./upgrades"; -import {options} from "./options"; +import { rawUpgrades } from "./upgrades"; +import { options } from "./options"; export type colorString = string; @@ -301,14 +301,9 @@ export type OptionDef = { help: string; }; export type OptionId = keyof typeof options; -export type UpgradeLike = { - id: PerkId; - name: string; - requires: string; - threshold: number; -}; + export type UnlockCondition = { - required: PerkId[]; - forbidden: PerkId[]; - minScore: number; -} \ No newline at end of file + required: PerkId[]; + forbidden: PerkId[]; + minScore: number; +}; diff --git a/src/upgrades.ts b/src/upgrades.ts index b5cfa30..3963a2a 100644 --- a/src/upgrades.ts +++ b/src/upgrades.ts @@ -926,10 +926,10 @@ export const rawUpgrades = [ max: 4, name: t("upgrades.passive_income.name"), help: (lvl: number) => - t("upgrades.passive_income.tooltip", { time: lvl * 0.10-0.05, lvl }), + t("upgrades.passive_income.tooltip", { time: lvl * 0.1 - 0.05, lvl }), fullHelp: (lvl: number) => t("upgrades.passive_income.verbose_description", { - time: lvl * 0.10-0.05, + time: lvl * 0.1 - 0.05, lvl, }), },