From 099f907972beaf3736a7348be665b64d4ffa14a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BD=D1=8C=20=3A=29?= <88856726+leo-need-more-coffee@users.noreply.github.com> Date: Mon, 1 May 2023 20:39:37 +0300 Subject: [PATCH] Add files via upload --- applications/external/bomberduck/LICENSE | 22 + applications/external/bomberduck/README.md | 2 + .../external/bomberduck/application.fam | 15 + .../external/bomberduck/assets/bomb0.png | Bin 0 -> 4536 bytes .../external/bomberduck/assets/bomb1.png | Bin 0 -> 4529 bytes .../external/bomberduck/assets/bomb2.png | Bin 0 -> 4531 bytes .../external/bomberduck/assets/box.png | Bin 0 -> 4329 bytes .../external/bomberduck/assets/end.png | Bin 0 -> 4739 bytes .../external/bomberduck/assets/enemy1.png | Bin 0 -> 4757 bytes .../external/bomberduck/assets/enemyleft.png | Bin 0 -> 4761 bytes .../external/bomberduck/assets/enemyright.png | Bin 0 -> 4536 bytes .../external/bomberduck/assets/explore.png | Bin 0 -> 4540 bytes .../external/bomberduck/assets/playerleft.png | Bin 0 -> 4311 bytes .../bomberduck/assets/playerright.png | Bin 0 -> 4307 bytes .../external/bomberduck/assets/unbreakbox.png | Bin 0 -> 4763 bytes applications/external/bomberduck/bomb.png | Bin 0 -> 4534 bytes applications/external/bomberduck/bomberduck.c | 645 ++++++++++++++++++ 17 files changed, 684 insertions(+) create mode 100644 applications/external/bomberduck/LICENSE create mode 100644 applications/external/bomberduck/README.md create mode 100644 applications/external/bomberduck/application.fam create mode 100644 applications/external/bomberduck/assets/bomb0.png create mode 100644 applications/external/bomberduck/assets/bomb1.png create mode 100644 applications/external/bomberduck/assets/bomb2.png create mode 100644 applications/external/bomberduck/assets/box.png create mode 100644 applications/external/bomberduck/assets/end.png create mode 100644 applications/external/bomberduck/assets/enemy1.png create mode 100644 applications/external/bomberduck/assets/enemyleft.png create mode 100644 applications/external/bomberduck/assets/enemyright.png create mode 100644 applications/external/bomberduck/assets/explore.png create mode 100644 applications/external/bomberduck/assets/playerleft.png create mode 100644 applications/external/bomberduck/assets/playerright.png create mode 100644 applications/external/bomberduck/assets/unbreakbox.png create mode 100644 applications/external/bomberduck/bomb.png create mode 100644 applications/external/bomberduck/bomberduck.c diff --git a/applications/external/bomberduck/LICENSE b/applications/external/bomberduck/LICENSE new file mode 100644 index 000000000..bce361a99 --- /dev/null +++ b/applications/external/bomberduck/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/applications/external/bomberduck/README.md b/applications/external/bomberduck/README.md new file mode 100644 index 000000000..2d133145a --- /dev/null +++ b/applications/external/bomberduck/README.md @@ -0,0 +1,2 @@ +# flipperzero-bomberduck +Bomberman clone on flipper zero! diff --git a/applications/external/bomberduck/application.fam b/applications/external/bomberduck/application.fam new file mode 100644 index 000000000..afcd5a6ee --- /dev/null +++ b/applications/external/bomberduck/application.fam @@ -0,0 +1,15 @@ +App( + appid="bomberduck", + name="Bomberduck", + apptype=FlipperAppType.EXTERNAL, + entry_point="bomberduck_app", + cdefines=["BOMBERDUCK"], + requires=[ + "gui", + ], + stack_size=1 * 1024, + order=90, + fap_icon="bomb.png", + fap_category="Games", + fap_icon_assets="assets", +) diff --git a/applications/external/bomberduck/assets/bomb0.png b/applications/external/bomberduck/assets/bomb0.png new file mode 100644 index 0000000000000000000000000000000000000000..3fdc3a3c12c7ede770e1c99c2003c777b03f4d75 GIT binary patch literal 4536 zcmeHKYj6|S6<%y!HW&j1Oo@SwNCLLA+NY$|R^nmFU;#3+tr`c~z&`HETT5CYtu5IJ znE)k#DRI*@1C1$^5T@xs878Hv(-e#gv`h*^utTUBhjB~-37JAnNeB}jy}R;rl9`UD z<)1Yp>F&AT`R+O2Irq-qExw{f8R^r~5d_Kb6uL{`zdlYModSPTeC5~R-}PF5xmLo* z(MVL4l^{U1ng~EaLXi<9adBI5+qM(v*n7XN! z8V(A9salG3vEWq)igso#5Xb;gQUCQc;F zHl-hajl?w1R1tbak+dRm#Zgp znD5TDFF6a3&(A)&s&#QeuBm!_@hRW0pWIycY1w|?Pt*65Rh)1BxFvIs$JNr=Ij3<- z_TBOWTqFDWwT|4;>t~_|%|&(QlFkRe$lp3O^Tltvu3x%*eLDL7lBIu0A?LT|$+;7< z=(fq^*LBDX?`d9zI*S=Gf$2EV#^6q-Z8nes`Gbe z>Y8hIv#0CcT>Na2<0ma6w#7=2vkEQ_+Am@+1G;4qo@>a?!M*0|4W z?`Bcv{X74}R_@EKy!3Jt@ypij+Z&5wXWSq5 zcl@O#k6su#)qbV;g^_Jt8y+;@2><@>iN=OWb*a(T&yMDdx%FYnkN1bw zGi!IwMU-o~HL2OzDYHhr`}DsP@xU|cgI&s3w^L{Mqo4n)^w50-8Mjh_tyu0|%86>o z%uA{O%!yD0_9%il<|QJ$SP3*#00AZJG~IZo$%HDB)3n^;CA<+As89-PqoB05$S>Ab zigw8~Z*ICH!9ju$(0DWv3Wj4`!f7&iIXKqMxCu2NTBXxe?)9NAH40G1%$NzRAfZ%K zrn%{;BPz*UiF;u;1$=UvDl{#^;dneAH^*tS8V%s2-EPMT3a2OxBCuFZSmP5|I5tbC zNOHJAOpGcKO;N+B&dCdEmF6^=;5^zBUnt`B_R@!A-6}vm@B|;hNi%_mLU@0Vm{w2? zNxB32PLG%$?r6LO#MG*&2nwn}Sewcq76!AE423Z^n-#M&7B~`ENt7+TOF z%VPjoWJ(r!t0>b3l_YWt)o6%^wI4Xbg6u&PftxIys}4g@egJVR^kzA%Wom zbKzW3z-wyMuc|?(Ne>CtJ$t9Ua63u7#=Ch9KvIIDIfCJ6!cUMKVdE%!9sw==@T#Q9 zHUAB*ZywZ{51CBi0%mSl_e3i!XI*xM5{F)&33t{;m%MRnlcDti*p?;M5FByI3~hQ~eLd){|z z2IGC0pYC>hm`kAO&?1A8H;+Tm(fQ3^K4=PV`Vk4%l%WMT8i zU6+p|2Sy^F9<5lqb<_El58BHnhwrG5w6+vqZ1P6;XZ(eJBr|7J!+Vem@e~xf59Y64 F{~v;POwj-U literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/bomb1.png b/applications/external/bomberduck/assets/bomb1.png new file mode 100644 index 0000000000000000000000000000000000000000..11d05b9b7c445452253792c5a51ad6448cca8aee GIT binary patch literal 4529 zcmeHKYj6|S6<*swEEzB`38t=zH-ZE|vf77MudM_zlEDIGgsmEfOoR7vSKeCE3hmmG zO&&l(8cb5>#Xtjvl7wkGJcdcr)G0%W3u&1IPlBCsjCSvy`~0E_FP>t|H6jQy#aHI7fOl4^|{MfZC%F{ugZOhB<(1vZ>mp)M`9skt&V!ivdjpyd=Jdl<4+CgUF)_3gPmz-S7 zeUE&xdgGrypCtbQUqyHSbJGVa0==Q#HNSE(ow?bsJhy~+V>;eeuoi1M`N_te6@C1w zxyygCxnz5wuSw*{zU?urHW+Izp1knw{zZ=`l)ej_uZQ+sne^e`6Y1A7bDu$ww2hL-6YzOFgNeg* zcRc#MyX@!#dGD_7TvA$OYM8d-c;J`!KizzxYH#34FDVxXq}mN zy?P(h>iDX+yC`!*K6=1h-fXVux%I-r&9kz9{$2mY&(2<)jefLr*>BUy2Re(zqUkx7 zuDi%@nvthI+)SQ0eu5J3Ei`=4U!R@7y6+X&``>-K>(z(aADnz?(=k%qc2`e*&u`kB z+ZuN{PBg!<-9gs-F@&K%TbZBF3!7eW>#e1n`H6Jx&3q3ct2L( z%c0DBcl_Q_x2LG?vlovLFLiF++FGtmGu&S@eTKK-buQ!H;IutIp7-v;=BsD#zM1wH z{Q0H#oSHPt`NfK-CUx~cajUH_y8rsI*6nvTXUxXmxeE3JOQAM=1(sjMjuDx1oKd{Z6o z6if@|8(m2T5=4N?qRB`&sxV2nN#|wYSTo}$REMZ_Zd0{CfO_OOKxs2=Ca}_^)Igc$ z8&OwW5Sa?^q5%r{n(Ik{eSn@n&X9gHs$^ZSSBqso8^P!BxG#&FV1;E@PE(nC>88z9L* zK;P@31mT9pD}W-`$9YiN0HW%gkrV9tU9%flvjmN{(7`vCkhE^3Ws* zNs*ZD1;rkPR3&j(tWmLPGkQ8B1A*>Cyra;Ax$9tv^7|RD%-3t-`MhqEwmu`syd*IC zkmfi$&su5BNzxQX+wC^YNn7EFa|pa>W$hfzj-c{I6_t(hK%;`>W(o3$qJ`pEs|}-V z0A3uNh;ck=#VDI-rwGE8h6akegtEoxa9F&8wktAuekd)Il45|Wg1$LswNfKrYtVPG;)SXS#(NTAzc zE{rD*SXGV(WjX9NX(6GS=g_ntZYP0NSud*sNJ>x^hM*Y>5hO^4aKJ$^0WBl&vLK0# z{|&8e9@Ld8d6}fZ^&53lYDZOqHL0i6V_4F+5{l}Zf?@eo3JTi*1U*j3m73yf*=PvB z(_^4r2kp}Lv;qlBE!t@d#&HDfA<+WsXAv!!jTA+aA~*_=_R;K$EUF1M4oX5$N2nES zPhBgtKrd9`Xmp|$XjOoMVFZm)&LBlHP&|qp5DdTlDbg0Z18^jPIqY!P&{mGbSc;=C zo~JlMw32o!aEuQ6e@St;C;lx(7p@(PgGF`W|55f7V8l5JrAgV~`3#SHeCWI%&`dj7 zZ{u&E-EQLwka~QPG3h%l*SK6`QeaHr@$MRzYfK7^2|V6i|2Mge!(WUb3SaaR@O!W* z{^U#WThb6Kdr(0T^BnD;mfW+T0UGa6eg4ur&QF*zcD`;u^wIl|ukC9&oAubK9~ufwSNA{`#8+DGJ+QE5!@mG~Pe@e& literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/bomb2.png b/applications/external/bomberduck/assets/bomb2.png new file mode 100644 index 0000000000000000000000000000000000000000..38ce7c732bfa5e3586d1c9b9a754b85405cd4566 GIT binary patch literal 4531 zcmeHKYj6|S6<$9e*oGLGfT_peML+;Mt9|ORTZxAyg9XS4TQv?$fqmSSHA3^WiZAxzpKrA(4i6NVBeq@^iL8oQJ_lVlvzgcO=MrVOMFkKSGRIn7MR z)AG-nk#zUmbH01dcfNaP@3uhs(h1r5*$9G6@RfNh;J-1>9+wV((*xC4;NRzs!D_vN zPoS~5Dl1`t>J2e~f}|oNNb>!sS9Lyp1|5I!#1@WW-qE0gfHd5>Z{-}`g({)!%P z&Fqyw*}iyhV1DPvt7jJf<#OZ15A%B0)#T@#dW>FB2{Wmz+EVqawu+sH-rq1`&9jpy zlT|<1w5X}~iC<=pA#T>_x2q1FK6xT>z4Q)U)tK>KD3S56b|4{0TC?Ku1biM(f8ns) zeNE4}%ida4@b>zSWu--y`iZN~2A+RtYs+Ue|AFQgm(Dv8%+=D((dw2J|)~N-z zs$b?>oma1P6^+|ch#s|;w^%E>@BXM{`?TC0U-y3T(WNh@qkmey;?;C=QAe>{G%1hn zoI-xpf;{=h?c}+$=O}s3{H%9->v9X%_q^cx!`B}iIJEZs!{fi)c7~MqOzE!c{`vWq zwuS@Fb1knd+f?p)qTt>!A&kCVS`oOvsoMoOt**8PHaR{sv3be)cHmW zQ=i}$H~(#Ado6~=Gp~m;@-AZj&J1hfu{(1;cChqX#{<_Ix^6%9oB27{KTQAbk*IpU zY2N}wxl+`SQBaURYs@?A{*g?C9#!w|S8m+Qm=TO${k-zn9R#_5tpb%;?O(x(YQ)M* zssOCXNDN98L0k)yF5Y%C9ojkO{x zSr#tHb|pCo5CJ-mCL`gf#wFbr6PJTy!;D){(?zd!TdMs5)T71$%2*jIft4neddjjO z8+FAcnXB+F>4ShzZcB}>$2c5MBofvHZB^qToMc%RCn%hvFzA744N;v>Vo`0D0g=M+ z0!@r7FA_Yc5FwLTUgA9#|F;iQ$oBN2RPgr=9)Ly*3N zzA-`z!VQgA08Ooni=ea~MDLA4a?1#G0Pd62n-*<9p>F%yXg$Q{C>`>igiYMKCjzitj|fRs7RbS zWCXz>@-_xzNru80hr^Dsj17(irzFZY-XSpj5GY?%)A^_f3@8Y0RUnR?b~3cU5}4f~ z*f550Ix&G_Y#3o<8PXxM5=D_iAXdf|s7gLOG%Ev2f>2J965#Q~q&LRpDHOCZeaG7NBARw&WB zMoOp=IWX;q+ezYe-plI%f)W(X5e!EYL4xE677mIDXc^+KN{Za@ z-@J{@gSt{JFH!Uv6i8X3WCufIfj^#%7Kb2@kSi!p zlPh$d*{J!$y%ROS=mI1RBN&WggA~a@@+h*8F#O(^DB5|_LECvuq$B~Vof0u814xV( zL`oK%EW_GT`WPVae<^WL6V&h$UAS>9_BYjq|3}+X4nxjSNKMKH&u4ht;{)e?A7?P% zd->^;+r3-@MMoDI5x=8!jnXwD21evOs;*JGM#R8~oJZC5f1@jV@Wu$D@I@~H?}KlC zwr(rDOJ>E&9@Y@VI?MQ`B@ZvGhsOJKpTG3J%bC-sW}yQA_qEXUExoi__oxx$nt_;a zzd%A0ie7^nZ@;TI-=Ak(Onu(P!D$^$JAOY2A;zUQ`|e`93fbA6h0fPYDxODT?2Y63 zPrW*&>7})^$)cW1xch3(p$l^^t>3Zrh@Ae&jG38f-#JVCB8d4V+w@^|y107;Q8`s!r9<>K*$8}6g>N;sjATc4yq;7b1@BE%- zrsJ9BKTD(2-nYN+x8L{MZ+CY0`icq`7#=X_bh-teLU#%LSKEdZJ$&kYfvfOusKy^q zN|-njlSEz!14OBg0R$ujUZ+c3db;>8Pj}!cx8h58=&|)#uT^{c+77htKeX!Lk4s

Y(%&x8cXle1Amu0 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 W?%Tg+a|JX){N>AiuP%OK!+!v0;CsXX literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/enemy1.png b/applications/external/bomberduck/assets/enemy1.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee7cb27f1ee52c63dbdb31e788c1011c8448d35 GIT binary patch literal 4757 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 literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/enemyright.png b/applications/external/bomberduck/assets/enemyright.png new file mode 100644 index 0000000000000000000000000000000000000000..45e6a861ad9c914af25be2b6c1b6097fdc6f0d17 GIT binary patch literal 4536 zcmeHKeQ*@z8DB1lAqc@j2r_}Jiy-;f+mGA(T5^2kE+mIsIKnl=p;q_f-OHN0+so}H zccEZKiNFixQqR2oRlB(;cCnh8})Y=IykGX&Ci_wqS)rjt?r z%gx-~yU+VPzxR25&+mO_-_8Eg;>l^V(hvlh>@D$>!GC?6mTH2(CVxdY{JXd=P@$D^ zaWooJBsm07tu6{skdP$=NqqeLsx!|YCsS|5GuE26r?*s_<%K)0d_HgfpQT@K{rQQk zbkhfp{lEVQe(T?u?}bl4uHRlbRaGxUXH9--N~`$noc3c^rmb94h~zYGX`6RB!?AwL zM?z}DwKcCqn~$B0?|C2Dwd=<8$$K~0(k8SBG~VN8$|f$ebvb8dDA%eFfZzP~t(!Z_ za}GtVmD653;OLz%X59Q)p9wtE=SLlB{umoxE$o|^RRM=$LuIC=B$4X>T&hl;nE%+l-|;N?9iK8UFm>;DAAGm4{`&bjx5vFt zY<=kd(-USoKU?+8gfl%)_Z__y+24D-`Ipn{Q)UwfZ&CM*k8fPodhp0k!|zm^ZZvGn z`@^Ti>5UgwwpZbJZ2Z+wO6F8}f1vd3lCOW2GA9uG;yKtp*Dlp`+e(mO{mR2E&>8mo`=MctrME?E}?tJjqVgmqPd zQ^Xc8N-IdP5FiXR4o!qZ5tU82Fawu`W8F+(sNtejxv&bKA9X7+fHG#rOyWfext7Kj zrJ)5eQDVzH%laYUlMAcVv?xmu@p#-Ex0sb!kf5ASCqdE#P2n_4x+jBWgbjkPjlkMG4AG65%j0JVMoqY9UB} zLSGx92H=h+%7CiW!~{@O3nJRw;Si!Q7$2>Pg^Y4UfdC;8hOR1Hl^U^RvDfDxjL<0v z%HgOH1<4-asman1StD}OXN+=&Cj!F+Z> z#Lz@Q4ujPir?W}f9D2G=lD665FqyM~R}Nw-RHBYak!A~HgzIf#VKIxgrdf#U^yXKg38qb(Z~~GC8vZ+E)oRr z^yruCfL;C?DNvF~OLoSB^E?SPBw1kpERqGcQIbT_Bu@j%J`!D3BrVRxz|tV(5po6P zX>f%uFdCIJ(mP%W^e#ZcaFW4kXMmR^z-Z&KorCg^@m^p{vb=*QwfQwxayX?xOP*f|QRN!sA~43B$a@VxKm z4CZ?$KmBsMlS`oJ*dn9icZ{wvx<C0@_cz|4+Kr6;E#Xlh|!U&95zbJP9;$F^rDco76M zz5V!0f4N3|vZ}LQ_N0&Ui#rxRF#k)4g?NifJxzs= GJ@sFi98UKD literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/explore.png b/applications/external/bomberduck/assets/explore.png new file mode 100644 index 0000000000000000000000000000000000000000..5eb50b669b3ee364bd25a37991519cf833660ae5 GIT binary patch literal 4540 zcmeHKeQ;FO6@MfFVKICS5~M+%n;>Mv+xNL2?{$}u?1p54jZ0WCDOP=-n@4u{ExT{C zn+O%Cm1dzR>NKrHD9yyy0WywM2%-c=QA^3RBvOVJZ47D=Dm22Vts&`syZIcQ>10~| z%g*fXedqqp@1FBJ=iYg@-cweRshg*RASlyS>MRHU+E_O^4g98gDz1XR>vi4=wVaK? zp|B#!ei2q{Ln183WeI}ffBD(!%HU~ia_?7pbs1(f``yaD?|<)&%Wd`UXJ0CB*4I|- zWKYUZJki#1;r@=?%9ca%ybRpZFs`AeTf1S8;ZcBr2Q~kD%A7$w#ojFVfdSKnl8996U=Iu-z{rB9!`p@z{U;5J8 z6~>1%tBPKmv;Bi74|4ndT6pWV#M4E!##_3^zF!);a*w|{%X9vLmG)g5wwr%tSeVN# zvD&cedv`3_v~cm3VL zagb@XUc1_5n7nNP++r+C7|Xl+pDo%kclxexdai$X`TBhL{gtZ@r{T*w^CiQ~Eb`(# z_}2;OsXy(&&%Sq-kQU}m`D0IX`hrJq{Mz=1Z!Ya?THjuI_do03#-(4}(;e-8xjk{J zcAxcZ;?)(K%4{1tCe|-F*3#Ph&atjnPLgj)jHx91fjLtH2Y-j>zc8;Sccb&XdM1l7 z9%wvjt!_3{fB0M*_IzhULu*-N#*`(G&79?2{97)4p?5~}+C`^}5?@}vuW!P;=oBxc}6R;Gy2PTldUPq|Zl>+{W+Dh;3coex&W`!10Y~U+>$R|K=y? zg{_}G*inrj;f!1U^sEbr`(nB=wxw^8!z`A3(K-8z+OFF>PvlL#^+DPX4+NF=&5cVT z`KqBdJv%!sXX2ShZpLH2$CduQ@|Rzw-{%cq`+UtSeGoKly$o8h!o7;&m4J~I6izh8 z10m3(5M(QehgiN^RAEl^$w9mR#_={iEDLu1Lnb%o4mrdsxwI}UuBj{Y@^#fbE$9oD z>TGca5ClY(h2sH#Fv7&``Xny{#+n(`!%2u*ZP!=0J+MOwi!f!Rj2KcJmum?9QXOmy z3ldZATs}Ynp6vQ6RShvH8jHn@G191neJD=TG>Q=@K_CEuL~4U78%KhX9E~Ey;S?i$ zSPrSO5`;BQmQ$jtU9Si8@L+s_klQ^(AB+sB0Q5lPYzW1T7#awmBRwK&aSb3D2~Bh0r)fAe6;oMrg_eMx0gPB@=7mD0T#uD;QDPATMfEfZQkp9$Msh!Ax)nX%Sh3 z!Z8A&B{Pkf%&di`DcWQ)aU&=m49lP^S^vnWG%5j5S#g@93EG5kRsusP+H6Kx!O9|{ zXp#ttXU)7sCaDCTS+0ZwEGVZOV0|JQ3i^^0n&3>K$7R6agEAqYT{-qVa3cOZl%mtD@_c8)`{T==tPYZ$BZPEoYBg{fMkHMtk$Q1AZZ7= zFpjXus!G_aD1N(M3klXdho;?NI|;1HI$2c&q!>Xm7{!p77sDAGXH4dN3|L0s6+xD2 z{~KD{Jg_ZQ@=`eh)~`*PQafsmxH0vVdi2Z5tpvl#O~J5yDuoDJBMQkl0at2@uVRBf z5u6?a?K)_ezoQj!NgyN(MIsyrx`2{MP(M;45i>4HIDv75h+9UpM-)kov0<^$2Xq8l zf%Z&l1usq(DsMD8RwZgx0D>VHg%Grtz!@MOfe#3V-uVzZq&VCY*3l{2Q0-V8EUFFtR@qa45$7n7CS?QXGdS+iq4Rz~ zGZ62c{0y|)om>Kj#}^rszTq`;WKK zgX^A|eG=Ryr-Vu?BM@ZF(Y_Pn%>^~Uc$eyO7vJ^wjQMk>GKWmDCSbZ(Ev`@N`hPz0O0VZ)6#7jA;DcPn LWzLqO$F}_kO43W9 literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/playerleft.png b/applications/external/bomberduck/assets/playerleft.png new file mode 100644 index 0000000000000000000000000000000000000000..86997a985eab4de991e315858b17ed7e0a981f74 GIT binary patch literal 4311 zcmeHKeQ*@z8QF~0mx0CKOUBB$ywxh6RdktHd zO&sK&?)m!b^WCRH-G!^$_a}-oP1cspFMM#|(!zW03)g0!TE3v}Zr#$0vELZGUb-+n z`tcmk4f{`Lq#nI*_apMPhBtb)weEi5)l-XhEletV<{4f2+r2_Tt8+zP&D`Z{#O4PM zw@BN!PF|&d&b$BEbZh?J9iP53`MlWoqIZt|$djhBXS3*cf4?u&_s3n;U$vdPIJM}q zyDDYY=lAB?FP7$K9CysB>pXqwYT(LU>tF7-mmbMD`&m5adGiz;K{9?OIh|g&(>Yi; zEO+PnEsn}J7v>#X+q1Ny#LzTt#XH_#-}_|hvzoo$C$e_cG@S1GxI257+u7aQThwu9 z-p$&5Y=`ah%NI%}J~kI^H&&&L)xG^&7d@4mz4@EID<6JzWj6Yk`YQlbF=yi*SStB z$7fQ;y*ppCHMW&Bez>iZ_(e}kOGj07+N66Qntq3?=(m3TJm0joAI?9vD0Tg#Ikz(2 z#<$#`e`Z21^UoC1X2yza^(+#y2cJd9d@@;Nf+;8?75k zk9>lk*>GujcO!;HGOq>nGtXe2vwCCv(OdJK7O>>Yo}4d}7ruS^_2S9b&g<&-hUAm$ zcP>Dr%Oy#DUY@Stw&M@}I}xw{vE2W>bp0#+9AD(~FIFD71v@k$!A`98EMs{&XygRh z4~&Um7`7;a*vk@Oj&B4C>Id~w$YHp8xYK}2g2S-N>>)g1Cuoo=ng}@KRhhvd|R*t~qAOM088ilixqo!Qq_IQUPR0-;( zU|5TSVvj;9k~l2ZsN7VKR?f&oVE7R4DD+_M8W^HH9@ZuEF*QB6%VALGX9by;1Xdeb z7{bDdem`cj5`K)fnynZ|GXzF56fZCWPf~ty1eH4!Rk#ojR4Pbrlpv2;r2P~iIgB$4 zCXD773&vP^9<$I^nimA#LYajT6w4zL>`E>$GAorzfK)U=`YE0Q7)euBjJD7MW+VIn z1F&N#Mzs3J^%e`)gfie=q7H@!4L>S;OER#a9 z#IVCB1;I*%Q`ICbHp^;%r^peXEC(D0H6>Jy9CCZ$b`m&+b8!lQqy%MR37VxC9~_WombR7>&@uuq3zC@p zUubpnp!W2VS4vShe^N80chpL-F8!2#3`p8mLQ!o~upFN*A<8v@^kPA-w2N=xLiGTi z9s}(BtQ=sVhBxBNdT&{7s#-zZQz~kLDF4ve87!!EByZ&!-WevYh zfe^d}#o^0RvHVgme9@W|u3Q~O5MzP*%}BJBH9_O;irZ6h`=^<+bF#_0?9Os%x=X33 zRh)8Ay@Mm#)es11Tv8fP^=i0k!w+Uckkjod_vQA)HkaRlpc8dnm-^T4dAzEv*jiU! zw5bq5w*DNv|C4Ed>zY*bKyJ>);=gX$e&|PQ8vlgvdH7{q63*53T>oG~`_lQyYkd_@ QKsv--QRQl1^w4Af0rThwxc~qF literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/playerright.png b/applications/external/bomberduck/assets/playerright.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6283d9c26d9f9582fecd0cef9765ab2b288576 GIT binary patch literal 4307 zcmeHKeQ*@z8Q*+ia)5y4BWi$k(Gn8(_IB?hw>x(PxI2RA+3tBttlv!gj$hEe0MKjw9Yu0 z(f@KYclYk|{+{3aJiq68-+6bdyQpBQ<{k}#AXA-%_G0+2j5X=W@Hg3AdI|o0QtK&| zi`gg|j)=Sv0H|CO1}KOLJc7i!x3Bu^_LJz8fnUUP+kS;;H^24s%j?g4kYWBKXnHPm z|3K#3^Hz43wbp$>qpKTTP5jvx5J?i!bEdYxN3DG$1-Inikb~*j8@qNKPi<`|Xx~w1 z_^^Lqb#`)S%f7n3j+B>o4`ih^JvLjDc6zV=VC8+9SD(V}y>VCkXjfmX`}n!<{ikf7 zqwm>cnavr`HO{S^b#z0`q0Q&&XI$O5k36@{+~2={$;PS`)(%Ih0xB8o}Px{Mi(W&9gzMTk?v{A6x+)kTqIB%Hk zuKFF;!V^of-dWeV!jXejPhWM){nCS5;=OAQxS!JOSyTRQ+uzSm+vBvI@9D{InVmII z+RU_=FJHQtlfGd-dPrLo*B18-HZI$iIqjL7*RH(((UrOApC4NJS~9t$GndbqF-L!4 z7WsJ`*>r9j*?y{>;vZO)arRo(wE630DtOC>IKABcPq9!!FkdeMlNo0qQ}-*f2qAbwn^ojP;OYM>QlF3g~M+ zBoExrL@|)Wst5-h)gUA<7)#;fM*PE7k${?xk0U?;1R+#{tCF`ZS>SZJM?4e>{6a9S zdO@*oL&^d_D%NeWDKlz1V*`QiBfPhvhjUlK5an_)c9E-6!gJcKn6f_O6FI@hs6(1I z^9BI)IISmH+`xHtI7@LPo~JXIcrP%SXp$O3R9tE+uiDP-( zU^4JH%jHqH$)`7Y0dJsr-ZzHg;fMgck`0WFN}=*8RC<~RM$U*EeO?o8AUO`F4J^P} zU^a6wPS(sNqVaLeaxoHQVL62$>jy+QP9W@04wv*!HTUELRGQR z36Bs2B{Hk1Nt(=59!={_M#@Z+M&l@G4Twmv6BSNUr_~$O8Ko=?Oa=6hmJkFeldkrQUwt~-#d(CIyK~ea!bf)CR?eIk_BV4#vLJ;i&<(m|1%CCmTJ7lNJamUB0b7xLZJMy99QE0kb zc9hCCF{s?Z5%p>ad}vgV%TeWO_(;Q@b0BDm)4tS`*;)USr5Z$+eq#3E;K!e!PrGF6 zqTlSkg?7Cym&HFjs47bfvH_+H3` NI2}dyL(A50_zI?I5pDng literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/assets/unbreakbox.png b/applications/external/bomberduck/assets/unbreakbox.png new file mode 100644 index 0000000000000000000000000000000000000000..5e65912d53405d04bcd05916947a8de8fc5239c8 GIT binary patch literal 4763 zcmeHKeQ*LAa#*}l_EHe7ZnC@CWRtz7rA^W{(9lqV#IcC`@ou`N$%f6g zNqff~tuoa16pDf(PzIfh5AYZ zc0^x)uxe6uafh&a*{bL7ZU6Qbb<5kAiybrj+}Rh~@;;c=`r;Jt(bwjk*l=HGc<$nP zWy0FK-<anGNJXNLodp5GUkF@7z+}L`+vf=pS>nE*`w^*Ni z_U6;Syz8-FAHI9@QDwdPLf5ja_k!=wuX@JToHp$*%~PERpXE}4zqxxy8>jbNS)SRy z@>E6J{98W$MV9Sf3mbJ^7w_-ie<6J6t$&>py|<-bI+1eX zxv+d_#pVKJ`q{kt)a>k(r(Eyd^KCp9_`TfUE`4`7wJWG}J^GHKB1mR|1eNIblry{> zGO&Wo0Yf|#ff7ZK{K9yI<%2*)IS`P-cKwCd_vukdu#O?Y7E(6D!*{DYoE^5%O_j|mkLskGv87Kpex#ChC zsV~r>`HCPimClj@2zX`JSF37-F&bmBm?35|$V$LS*lacfbbtlOhcV7ZjD!I4>q*15=7-%g$J%W5LRh^et zA~XsDQYey$f@F{KR3&kktWmjXGl_CWCIZ8Ua7TF$)}C;NULFtQl=)gMJ-5@Y*VbnQ znU@46F{C(-=2H$0(b{ zg0X^?#Q-piq{y=tUNj}31fD68l@JTJQwp&GV2p$Vi3yExrpW8I>q!GXZ1L8xst5z@ z`f@2;8y}wVNg=REWi>Vli8CrrtXS_GCSuacKFQlgbmG|?0c%O^{SvUNa6qBAq6xDQqDYW9M*@N#jUJUnHO4BS zC;)kcTtRszxI%ADY}9R|y<^ot+XYA%hEo`6^N|Dt$s>sY!i?9xL>#AW6ie7Jkpdh> z;gl8Qa1)D}N!Cn@g21zMQU^l>{x2m$P2dD$HZwT+|0|KU5QK@xO_-VI2#f+Ef!WM9 z8g?N`5VVyfI4;=&KUawZvbT;dG2f`&`3H5IZ~T$6lMW*u6>#^HHuwmFPc-AuBW*wy zFyCwW8R)2Mxde)iFES>6$LSiUYfKD`$$4B|<8+OQfiXFctLtZ@OE-Kd24VOv8-qvQ z89nFS@VI<^r0lLJf*5kO?}T_qVI4H4t8R}g{Y+ZU^)siu^qJ!YXqv9N{Hj9^X(uTp z@q!NoG$yIlsP=-tq%q?r=v3r(7WuM{bgbR4L-2{kD|YwygIHFp{{wKclAL^e-K+_( zl_?z?d^4U32Ch85aAyv(?N?isr~6iiN)H`tCH8?-F>_AFzD>vWLNLVbTHxGOd~ef# E080^$ApigX literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/bomb.png b/applications/external/bomberduck/bomb.png new file mode 100644 index 0000000000000000000000000000000000000000..44b9bfdeae76553be52ce1c451133a4baee7bf68 GIT binary patch literal 4534 zcmeHKYj6|S6<%z|5CMh~3MO%!MQ#F^?0fat9m^P72CE<}8sWT0;SYAG!)aM&4dO*36QBnfew$RC4{;rDG78SDFiYN#Jwv&HO)-N z)AG-nk#zUm?|k>1@0@#Q??%s(g%eE=nh*q;=qhoR!+&FJ8kY`#o9I&q;or4dZ-rhi z#L$SQ%1RKRdQAkNAg;&=5+SdGG+Oq zj?BQ7b)PkKHl)qI9nkMC+j;2q{r;QBzP_>NX8O53u?cgg)_sN`W1drriaf5OqJhj| zzFXI|I7*HbWF1>`=DXj^&8VJS*5!HmAKhbnDqi(8nA(>G&K>^f^rRiGqSl_C*>6tE zx>K=-f75>TN_XzK^^c%?@gYAB9E1UUb{n6%CTb}&ErB!-G_lrW#=509{4{SPSec^+jv`uJ>H`;&p z%7Y(|U%utrCs%Ggr?pwGcdf~Muk!e!RUO=hv}yY`Om+VL6<;c-*l_w6Ek3jRtF@DQ zpSe`pvgon*(=)lhm(`oPK7Y3N@b&PCcRp%(X=-EY!^9hRsg$%>{ely39BK}|wKnC; z?e%ki`Elpj`WH)2S7Ml!b~Bth{e8@RF%^$J^YyGJ>F+H3=b5Rd`?~M`=02|_>@(0C{qj`DGbIl;@rv0*06Xab^FI?NSr4_c&Z0A+C&C$ZwV zQcaulO=zAb$$YtUK|ck2a+m|U9^nZh7K`CA23IvdL2(>MkTgNl7(`&vny@a!v2ZlU zpy=apf~cq|5nWNksKF`t)GFO!Hp6*zAihwh^?6AZ z6^Ty_S)b1)3KkaQD3-=po6U-GtObsIc1e^ig3ZSY!>C;0s4j#>U{FDFT!B1Ri4p7; zn+;<~ABnLfDPf$QBQdL;v&f`iu}Dc2rJ4e}QV0%@%Ak@Um7U^z9L-rUpPhzOoYjg6 zl3l<6u*kG53RY2O646K^zd+SO0xYKz68wOOg#C#LLvVh+$K^27I5}kT1O;7&4i58T zC0rFBn(!(iuv8ZeH7To|wp$s7qDk7qaMTcJ8PKAz6Aey^#2Gd*W0Zx5$v|NRqfa40 z!VYuci!>nUs^(SIpu=p0gc_cM({8w(BtaLPf({@lNi#gj@(k&vY&=QvEH{^gmSK2R zQskQdhBh`2n%7tI5+w@PuSuBtcGOa^w(qI$F{mWA5{f1^1uuwwDMW>8ASL32Tzykw zKnVK*JU#l`b-=ECLn~0SM9Vgo!F)av_K?iL`Y|$tSt(hDvifL1*^=3#s;tKZ4b1mL z9idjRJri1?vlE4ylZ=i9fKde~7)G)f&3S2xhvLyxzhK0@Pthte5^LjF4A^V{W342I z`6Q9W7>*_d!AAKc%90%P|B~WhPgv;W6!Qq2J4txB{deU1UW1j>4ts8dLNDYP|hEQJ*m#g7RI?`QFSkP0jO7NWr)i=2q{T>eBHuH(vc!dPhO) z7cJG}kr`>8-0$DFdUNQ)ipMUv6x9pvoL~QvcJld^0sOV5X%F#bOaBF#5LfXM=ib7n G*8dyMBTMf9 literal 0 HcmV?d00001 diff --git a/applications/external/bomberduck/bomberduck.c b/applications/external/bomberduck/bomberduck.c new file mode 100644 index 000000000..7b8b5f14a --- /dev/null +++ b/applications/external/bomberduck/bomberduck.c @@ -0,0 +1,645 @@ +#include +#include + +#include +#include +#include +#include +#include +#include "bomberduck_icons.h" +#include + +int max(int a, int b) { + return (a > b) ? a : b; +} + +int min(int a, int b) { + return (a < b) ? a : b; +} + +#define WorldSizeX 12 +#define WorldSizeY 6 +#define BombRange 1 + + +typedef struct { + FuriMutex* mutex; +} BomberState; + +typedef struct { + int row; + int col; +} Cell; + +typedef struct { + Cell cells[WorldSizeY * WorldSizeX]; + int front; + int rear; +} Queue; + +void enqueue(Queue* q, Cell c) { + q->cells[q->rear] = c; + q->rear++; +} + +Cell dequeue(Queue* q) { + Cell c = q->cells[q->front]; + q->front++; + + return c; +} + +bool is_empty(Queue* q) { + return q->front == q->rear; +} + +typedef struct { + int x; + int y; + int planted; +} Bomb; + +typedef struct { + int x; + int y; + bool side; +} Player; + +typedef struct { + int x; + int y; + int last; + bool side; + int level; +} Enemy; + +typedef struct { + int matrix[WorldSizeY][WorldSizeX]; + Player* player; + bool running; + int level; + + Enemy enemies[10]; + int enemies_count; + + Bomb bombs[100]; + int bombs_count; + + int endx; + int endy; +} World; + +Player player = {0, 0, 1}; +World world = {{{0}}, &player, 1, 0, {}, 0, {}, 0, 0, 0}; +bool vibration = false; + +void init() { + player.x = 1; + player.y = 1; + + world.endx = 4 + rand() % 8; + world.endy = rand() % 6; + for(int i = 0; i < WorldSizeY; i++) { + for(int j = 0; j < WorldSizeX; j++) { + world.matrix[i][j] = rand() % 3; + } + } + world.running = 1; + world.bombs_count =0; + vibration = false; + for(int j = max(0, player.y - BombRange); j < min(WorldSizeY, player.y + BombRange + 1); j++) { + world.matrix[j][player.x] = 0; + } + + for(int j = max(0, player.x - BombRange); j < min(WorldSizeX, player.x + BombRange + 1); j++) { + world.matrix[player.y][j] = 0; + } + + world.enemies_count = 0; + for(int j = 0; j < rand() % 4 + world.level / 5; j++) { + Enemy enemy; + enemy.x = 4 + rand() % 7; + enemy.y = rand() % 6; + enemy.last = 0; + enemy.side = 1; + enemy.level = 0; + + world.enemies[j] = enemy; + world.enemies_count++; + + for(int m = max(0, world.enemies[j].y - BombRange); + m < min(WorldSizeY, world.enemies[j].y + BombRange + 1); + m++) { + world.matrix[m][world.enemies[j].x] = 0; + } + + for(int m = max(0, world.enemies[j].x - BombRange); + m < min(WorldSizeX, world.enemies[j].x + BombRange + 1); + m++) { + world.matrix[world.enemies[j].y][m] = 0; + } + } + world.matrix[world.endy][world.endx] = 1; +} + +const NotificationSequence end = { + &message_vibro_on, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_vibro_off, + NULL, +}; + +static const NotificationSequence bomb2 = { + &message_vibro_on, + &message_delay_25, + &message_vibro_off, + NULL, +}; + +static const NotificationSequence bomb_explore = { + &message_vibro_on, + &message_delay_50, + &message_vibro_off, + NULL, +}; + +static const NotificationSequence vibr1 = { + &message_vibro_on, + &message_delay_10, + &message_vibro_off, + &message_delay_10, + &message_vibro_on, + &message_delay_10, + &message_vibro_off, + &message_delay_10, + + NULL, +}; + + +void intToStr(int num, char* str) { + int i = 0, sign = 0; + + if(num < 0) { + num = -num; + sign = 1; + } + + do { + str[i++] = num % 10 + '0'; + num /= 10; + } while(num > 0); + + if(sign) { + str[i++] = '-'; + } + + str[i] = '\0'; + + // Reverse the string + int j, len = i; + char temp; + for(j = 0; j < len / 2; j++) { + temp = str[j]; + str[j] = str[len - j - 1]; + str[len - j - 1] = temp; + } +} + +bool BFS() { + // Initialize visited array and queue + int visited[WorldSizeY][WorldSizeX] = {0}; + Queue q = {.front = 0, .rear = 0}; + // Mark the starting cell as visited and enqueue it + visited[world.player->y][world.player->x] = 1; + Cell startCell = {.row = world.player->y, .col = world.player->x}; + enqueue(&q, startCell); + // Traverse the field + while(!is_empty(&q)) { + // Dequeue a cell from the queue + Cell currentCell = dequeue(&q); + // Check if the current cell is the destination cell + if(currentCell.row == world.endy && currentCell.col == world.endx) { + return true; + } + // Check the neighboring cells + for(int rowOffset = -1; rowOffset <= 1; rowOffset++) { + for(int colOffset = -1; colOffset <= 1; colOffset++) { + // Skip diagonals and the current cell + if(rowOffset == 0 && colOffset == 0) { + continue; + } + if(rowOffset != 0 && colOffset != 0) { + continue; + } + // Calculate the row and column of the neighboring cell + int neighborRow = currentCell.row + rowOffset; + int neighborCol = currentCell.col + colOffset; + // Skip out-of-bounds cells and already visited cells + if(neighborRow < 0 || neighborRow >= WorldSizeY || neighborCol < 0 || + neighborCol >= WorldSizeX) { + continue; + } + if(visited[neighborRow][neighborCol]) { + continue; + } + // Mark the neighboring cell as visited and enqueue it + if(world.matrix[neighborRow][neighborCol] != 2) { + visited[neighborRow][neighborCol] = 1; + Cell neighborCell = {.row = neighborRow, .col = neighborCol}; + enqueue(&q, neighborCell); + } + } + } + } + return false; +} + +static void draw_callback(Canvas* canvas, void* ctx) { + furi_assert(ctx); + const BomberState* bomber_state = ctx; + + furi_mutex_acquire(bomber_state->mutex, FuriWaitForever); + if(!BFS()) { + init(); + } + canvas_clear(canvas); + + canvas_draw_icon(canvas, world.endx * 10 + 4, world.endy * 10 + 2, &I_end); + + if(world.running) { + for(size_t i = 0; i < WorldSizeY; i++) { + for(size_t j = 0; j < WorldSizeX; j++) { + switch(world.matrix[i][j]) { + case 0: + break; + case 1: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_box); + break; + case 2: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_unbreakbox); + break; + case 3: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb0); + break; + case 4: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb1); + break; + case 5: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb2); + break; + case 6: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_explore); + world.matrix[i][j] = 0; + break; + } + } + } + + if(world.player->side) { + canvas_draw_icon( + canvas, world.player->x * 10 + 4, world.player->y * 10 + 2, &I_playerright); + } else { + canvas_draw_icon( + canvas, world.player->x * 10 + 4, world.player->y * 10 + 2, &I_playerleft); + } + + for(int i = 0; i < world.enemies_count; i++) { + if(world.enemies[i].level > 0) { + canvas_draw_icon( + canvas, world.enemies[i].x * 10 + 4, world.enemies[i].y * 10 + 2, &I_enemy1); + } else { + if(world.enemies[i].side) { + canvas_draw_icon( + canvas, + world.enemies[i].x * 10 + 4, + world.enemies[i].y * 10 + 2, + &I_enemyright); + } else { + canvas_draw_icon( + canvas, + world.enemies[i].x * 10 + 4, + world.enemies[i].y * 10 + 2, + &I_enemyleft); + } + } + } + } else { + canvas_set_font(canvas, FontPrimary); + if(world.player->x == world.endx && world.player->y == world.endy) { + if(world.level == 20) { + canvas_draw_str(canvas, 30, 35, "You win!"); + }else{ + canvas_draw_str(canvas, 30, 35, "Next level!"); + char str[20]; + intToStr(world.level, str); + canvas_draw_str(canvas, 90, 35, str); + } + + } else { + canvas_draw_str(canvas, 30, 35, "You died :("); + } + } + + furi_mutex_release(bomber_state->mutex); +} + +static void input_callback(InputEvent* input_event, void* ctx) { + // Проверяем, что контекст не нулевой + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; + + furi_message_queue_put(event_queue, input_event, FuriWaitForever); +} + +int32_t bomberduck_app(void* p) { + UNUSED(p); + + // Текущее событие типа InputEvent + InputEvent event; + // Очередь событий на 8 элементов размера InputEvent + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); + + BomberState* bomber_state = malloc(sizeof(BomberState)); + + bomber_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); // Alloc Mutex + if(!bomber_state->mutex) { + FURI_LOG_E("BomberDuck", "cannot create mutex\r\n"); + furi_message_queue_free(event_queue); + free(bomber_state); + return 255; + } + + DOLPHIN_DEED(DolphinDeedPluginGameStart); + // Создаем новый view port + ViewPort* view_port = view_port_alloc(); + // Создаем callback отрисовки, без контекста + view_port_draw_callback_set(view_port, draw_callback, bomber_state); + // Создаем callback нажатий на клавиши, в качестве контекста передаем + // нашу очередь сообщений, чтоб запихивать в неё эти события + view_port_input_callback_set(view_port, input_callback, event_queue); + + // Создаем GUI приложения + Gui* gui = furi_record_open(RECORD_GUI); + // Подключаем view port к GUI в полноэкранном режиме + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message_block(notification, &sequence_display_backlight_enforce_on); + + init(); + + // Бесконечный цикл обработки очереди событий + while(1) { + if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) { + furi_mutex_acquire(bomber_state->mutex, FuriWaitForever); + // Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения + + if(event.type == InputTypePress) { + if(event.key == InputKeyOk) { + if(world.running) { + if(world.matrix[world.player->y][world.player->x] == 0 && + world.bombs_count < 2) { + notification_message(notification, &bomb2); + world.matrix[world.player->y][world.player->x] = 3; + Bomb bomb = {world.player->x, world.player->y, furi_get_tick()}; + world.bombs[world.bombs_count] = bomb; + world.bombs_count++; + } + } else { + init(); + } + } + if(world.running) { + if(event.key == InputKeyUp) { + if(world.player->y > 0 && + world.matrix[world.player->y - 1][world.player->x] == 0) + world.player->y--; + } + if(event.key == InputKeyDown) { + if(world.player->y < WorldSizeY - 1 && + world.matrix[world.player->y + 1][world.player->x] == 0) + world.player->y++; + } + if(event.key == InputKeyLeft) { + world.player->side = 0; + if(world.player->x > 0 && + world.matrix[world.player->y][world.player->x - 1] == 0) + world.player->x--; + } + if(event.key == InputKeyRight) { + world.player->side = 1; + if(world.player->x < WorldSizeX - 1 && + world.matrix[world.player->y][world.player->x + 1] == 0) + world.player->x++; + } + } + } else if(event.type == InputTypeLong) { + if(event.key == InputKeyBack) { + break; + } + } + } + if(world.running) { + if(world.player->x == world.endx && world.player->y == world.endy) { + notification_message(notification, &end); + world.running = 0; + world.level += 1; + if(world.level%5==0){ + DOLPHIN_DEED(DolphinDeedPluginGameWin); + } + } + for(int i = 0; i < world.bombs_count; i++) { + if(furi_get_tick() - world.bombs[i].planted > + (unsigned long)max((3000 - world.level * 150), 1000)) { + vibration = false; + world.matrix[world.bombs[i].y][world.bombs[i].x] = 6; + notification_message(notification, &bomb_explore); + + for(int j = max(0, world.bombs[i].y - BombRange); + j < min(WorldSizeY, world.bombs[i].y + BombRange + 1); + j++) { + if(world.matrix[j][world.bombs[i].x] != 2) { + world.matrix[j][world.bombs[i].x] = 6; + if(j == world.player->y && world.bombs[i].x == world.player->x) { + notification_message(notification, &end); + world.running = 0; + } + for(int e = 0; e < world.enemies_count; e++) { + if(j == world.enemies[e].y && + world.bombs[i].x == world.enemies[e].x) { + if(world.enemies[e].level > 0) { + world.enemies[e].level--; + } else { + for(int l = e; l < world.enemies_count - 1; l++) { + world.enemies[l] = world.enemies[l + 1]; + } + world.enemies_count--; + } + } + } + } + } + + for(int j = max(0, world.bombs[i].x - BombRange); + j < min(WorldSizeX, world.bombs[i].x + BombRange + 1); + j++) { + if(world.matrix[world.bombs[i].y][j] != 2) { + world.matrix[world.bombs[i].y][j] = 6; + if(world.bombs[i].y == world.player->y && j == world.player->x) { + notification_message(notification, &end); + world.running = 0; + } + for(int e = 0; e < world.enemies_count; e++) { + if(world.bombs[i].y == world.enemies[e].y && + j == world.enemies[e].x) { + if(world.enemies[e].level > 0) { + world.enemies[e].level--; + } else { + for(int l = e; l < world.enemies_count - 1; l++) { + world.enemies[l] = world.enemies[l + 1]; + } + world.enemies_count--; + } + } + } + } + } + + for(int j = i; j < world.bombs_count - 1; j++) { + world.bombs[j] = world.bombs[j + 1]; + } + world.bombs_count--; + } else if(furi_get_tick() - world.bombs[i].planted > (unsigned long)max((3000 - world.level * 150)*2/3, 666)&&world.matrix[world.bombs[i].y][world.bombs[i].x]!=5) { + world.matrix[world.bombs[i].y][world.bombs[i].x] = 5; + vibration=true; + + } else if(furi_get_tick() - world.bombs[i].planted > (unsigned long)max((3000 - world.level * 150)/3, 333)&& world.matrix[world.bombs[i].y][world.bombs[i].x]!=4) { + world.matrix[world.bombs[i].y][world.bombs[i].x] = 4; + + } + } + for(int e = 0; e < world.enemies_count; e++) { + if(world.player->y == world.enemies[e].y && + world.player->x == world.enemies[e].x) { + notification_message(notification, &end); + world.running = 0; + } + } + + for(int e = 0; e < world.enemies_count; e++) { + if(world.enemies[e].level > 0) { + if(furi_get_tick() - world.enemies[e].last > + (unsigned long)max((2000 - world.level * 100), 1000)) { + world.enemies[e].last = furi_get_tick(); + int move = rand() % 4; + switch(move) { + case 0: + if(world.enemies[e].y > 0 && + world.matrix[world.enemies[e].y - 1][world.enemies[e].x] != 2) + world.enemies[e].y--; + break; + case 1: + if(world.enemies[e].y < WorldSizeY - 1 && + world.matrix[world.enemies[e].y + 1][world.enemies[e].x] != 2) + world.enemies[e].y++; + break; + case 2: + world.enemies[e].side = 0; + if(world.enemies[e].x > 0 && + world.matrix[world.enemies[e].y][world.enemies[e].x - 1] != 2) + world.enemies[e].x--; + break; + case 3: + world.enemies[e].side = 1; + if(world.enemies[e].x < WorldSizeX - 1 && + world.matrix[world.enemies[e].y][world.enemies[e].x + 1] != 2) + world.enemies[e].x++; + default: + break; + } + } + } else { + if(furi_get_tick() - world.enemies[e].last > + (unsigned long)max((1000 - world.level * 50), 500)) { + world.enemies[e].last = furi_get_tick(); + int move = rand() % 4; + switch(move) { + case 0: + if(world.enemies[e].y > 0 && + world.matrix[world.enemies[e].y - 1][world.enemies[e].x] == 0) + world.enemies[e].y--; + break; + case 1: + if(world.enemies[e].y < WorldSizeY - 1 && + world.matrix[world.enemies[e].y + 1][world.enemies[e].x] == 0) + world.enemies[e].y++; + break; + case 2: + world.enemies[e].side = 0; + if(world.enemies[e].x > 0 && + world.matrix[world.enemies[e].y][world.enemies[e].x - 1] == 0) + world.enemies[e].x--; + break; + case 3: + world.enemies[e].side = 1; + if(world.enemies[e].x < WorldSizeX - 1 && + world.matrix[world.enemies[e].y][world.enemies[e].x + 1] == 0) + world.enemies[e].x++; + default: + break; + } + } + } + } + for(int e = 0; e < world.enemies_count; e++) { + for(int h = e + 1; h < world.enemies_count; h++) { + if(world.enemies[e].y == world.enemies[h].y && + world.enemies[e].x == world.enemies[h].x) { + world.enemies[h].level++; + for(int l = e; l < world.enemies_count - 1; l++) { + world.enemies[l] = world.enemies[l + 1]; + } + world.enemies_count--; + } + } + } + if(vibration){ + notification_message(notification, &vibr1); + } + } + + view_port_update(view_port); + furi_mutex_release(bomber_state->mutex); + } + + // Return to normal backlight settings + notification_message_block(notification, &sequence_display_backlight_enforce_auto); + furi_record_close(RECORD_NOTIFICATION); + // Специальная очистка памяти, занимаемой очередью + furi_message_queue_free(event_queue); + + // Чистим созданные объекты, связанные с интерфейсом + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + + furi_mutex_free(bomber_state->mutex); + furi_record_close(RECORD_GUI); + free(bomber_state); + + return 0; +}