From 3c17bdb5a07ff3791c9a9b8624dde54e2be872b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?El=C4=ABna=20Lukjanovi=C4=8Da?=
 <elukjanovica@noreply.gitea.rkg.lv>
Date: Mon, 26 Feb 2024 17:20:12 +0000
Subject: [PATCH] Upload files to "/"

---
 0001_sprites.png | Bin 0 -> 4356 bytes
 icon.png         | Bin 0 -> 10512 bytes
 main.py          | 866 +++++++++++++++++++++++++++++++++++++++++++++++
 main_data.json   | 107 ++++++
 main_puzzle.json |   1 +
 5 files changed, 974 insertions(+)
 create mode 100644 0001_sprites.png
 create mode 100644 icon.png
 create mode 100644 main.py
 create mode 100644 main_data.json
 create mode 100644 main_puzzle.json

diff --git a/0001_sprites.png b/0001_sprites.png
new file mode 100644
index 0000000000000000000000000000000000000000..b529c4f7a19fe2b665c1714fc5503effba69d4f1
GIT binary patch
literal 4356
zcmbtXi9eLz_aDm)(I7(hWh`y@kZh5iktHF@AhH{eED71gP_j&ADQnqU?97xUYqIaM
zJYx$jXd<D-(r*^?{Re*YI&+_U?mhS1^M2oR&ogt^+{_Tp!p{PMK;TA5Jqrkg4o~WX
z%nYP<FFj*|^q>o{Fw}vR4+t)k6h?P#Q*8*ODus2|2};uY%uTHHAx1Iy&e5HJfByaZ
z2eB`L#e%R{0xXUs(}$#VV6juMJ0zKel4SxKGY*X*wI86-BpHK7k3yqI7^6m@QKWX5
zF=~i0k|cwS5d(~o1B?;<3=w^d5q%8dB<W=c?_mh*W(Xs-T@0a}3}K!0q3;<&-_zgj
zpbzb!zx|H>b~}9tN!sW`TIqvH(gKT{fnjE0m>DL_91~`iDSn<QevT>rBU8cxQ~Ux`
z!Xi_`64Tu!X0m)D0dk!!S0+95Zd#aGlHmM*KM=o>6i$-AL%ztX0T2jVGx<xW0=1NY
zK-m3^^t7#l9f&#cF$4onJ)^7VLxDNf_+Hg7*#-Om^2%S;!#w;U{;6;BCkGvzZo?qP
zd(6Hz&u+0-I0&&BE;<%yvzgg=Lh6?l=5t|*FE{T-JU`+T_)bpR5S_4~=whcXd^T8+
zt%9wS_iHQb_I={<-)tVdYQ-<n=}zbf^X5P^c4CTZ<8YFniE;|}sr6w^oyjRTzG}_O
zcIr)GDt_ZEmha0e+2a=l3Ke(ei$2(DR5=!L4=ujx<aK#-IDbi1-oNjT#%A>2Y_3i@
zhxxmKV-JlJ)jqsx?=|FNav$fcb$wp<RTeYu{K(?@xZj6#``pVTF3*Br{;a+uIe7F&
zXl5l}TIN^bF7dw~+ywf~QB&=W8tEzz<I>lK6*qVAp1UV)rng_q=e6iB#HlZ1dLJ(6
zy0%`fD-s=$@+QLBTZMjH!KBS_wdB&<Y786PkQ3=b4P$)LlaGe6GX$C8M&VoNZxPEm
zs%=|C=uydq{<Pz`dMl22&hh`yyv}x84_8f83Mzyz;xtx1xCvqLH4{ovb>E-Nk0)Pu
zMSQax-{r0j)_ExZG^>!f@-MAtn8C>dRr<FIHXg<e`aU@Vu>S_70FSfhIM+2M+kN^F
z^)_b||7}Wn#&cgh8R8|&?s11l^EdZ^r}X#>h}7ZIkB<sK;f*s!>M7chQ2S!L6hQ($
zBcXglY0C3XjsIY*5;`n|ZGK1;4z`_v9Bn<e@U9$g`2`d<eG&-aWiP8!I^P_(_A!8;
ze!8XcEhpxX+|#~er%wUWBb7bI6E@mouxn%11AU{90yKnwzx`=#Eqln`SbFc&>vFbL
zd1df~x6s^P<7xNr$v;Bcq~SiJ``<oVRrI^<MG!<1onDBrEA~eGvS%O8rkB32a_etS
z9T7IkRjDF(`PfU9Q&*Nhq;WMhV~&@{hMgAPd>y`4h;NX<%}5r*<@kb^hx$~5P37w^
zFbtVy(EU=pVpVi;Q#XnER1-c&uuSaUXsUE#O6SK9KOC=>38%<SoxvBh2u;e~G`Z}Z
zUiL?OZ(LQQR<l^01*0_6@7%!>wwc0l3x5^!?IJg?2uFn2)&qMd5pTT<H7O3ZWgoa$
zt!?Qvnm{3SE10>zFrrg^een5TO^)+^-p1B{7yV#}oE19ND|w}o9=+xP!}f>EI*%7U
zUF9x(a-)C#baLKG<2T3dxM0Fh`yF1w^L}d%2KnCmG8hfv!)QU<w$P!W5^1HRYsRZp
zNy-;YZoWO8J7$`DROBRUISV^_bHSUwA(Z)hLZ?FMw_M1rC~LowF<Qc%A2U-PtEk#}
zInT@%3Ir=?#fik)CylZ!n78q}5wG8W72%)rVyT5;UXi_`Urihs=gUX&{n$tM0g<g$
z&942|#1f@*dr(BCDc6L57e0NB{;yWXdhZGYy6GN71wPQ>Y?+1DeKm!RT5A=?d}oyR
z$lt;T>)H@27mQqA|4dc#_;JS+ezDY&&g7U~P1RnCjP={wE`W!`az%b`eo&ON;6!LE
zOQaKkxP81IXIT9{;|qihK4O;?elze<TW6KU>apwc-+nmeV>jJ|+zjcP;s-sMeHkow
z?2bt_#ws{h)=K4hox@@-_eN_yNwE0ZdqG3nmo2+Ed-ccjrs?mtGeL}@9>+^Nr#(t4
z1H*p(tj?}G_x{VFJjFMrJ2ml^Z<VrKyL?Y$iXzm9j_=F_Y3K#8WdFA?xg7KvFW`8w
zWuei^>G?vbW08%G+3$V+XKy$+s<a9oG$2Sx_JSyT2wYznz9F9ZBq7-Z|8!N(VeQWe
zy4TXcL}-u{c2=pVHe+paBWBI<Fp%dg^A<=nxs+61^{@>I>@dvWb`bnC_D)4sIpB8Z
zQ)J?=4j+u=3n22Sr!J_N0d5<5H5l9aJP2sq${UstXzA@f8#sI61%D)X{_(m5a=f!)
zbz$kQjg54F3-7$85jx8PM0@qDVy~V<H<ag}_}b+nP`?jCmAB(j-QSrbZeo{k{!E2W
z8w!mCG`lk~<aqV7W*g4j-Nc{J&XRqwV*8jJqHzg4@B9W4J^jA81iyEw_QxJ}*30AG
znx+Y`(~e71mYRseg4;~BQ+wDX*_`d_2Fqgnp5O72woj5b^zFO|BEP?ItOOL9%K1f%
zW+PQl)#qiv^^!-HA!Cu2eh7Y_2i9iNWx$2@5{XGC1vP~!%mx%<l9tF?;i_$0t@&5(
zwP|+k<J!h<V%9S_?{t@lkK|6lD9o=mt->ToYbbr1oy58k5Y+v#|4dVD)N85rZRYf4
zPxo*CSroy$+72%j9(k-rr_uJ)Q`0<){a0Hho~=7Gxv>xORGr}PMiYQ`XWq9mp`&Qm
z0HG22BYd9pWGxt8n<FM;iG8Zg(NjZ=o482eusFjTyWt)BQN9)~iZB&@<W6917~3A;
zTiN{FWdYR*!N2w81!bQm-(Vs4D~*A*T!jAUr8(Xh^ISk~Iv#I~96BuVNsal_)OMRJ
z?rjj?A200~9?I-D3ql3~+s)$HfN8X&h7$zXq`tf4vc_^?A6~>ab(OVSorw}`08obP
zHKD|2?-d%E$^Jey3zu3dOo}ip=x5D>YK)TU&S(6iPN@P=O1#7!*)PFyZ+IQw{6*h%
z1s5W*-?)Y<V3NVIiLh+_gLN%4Gk19KaLxT){i9W(HS`|&HGj?TTs}OD^TntVgXb0A
z*z2`~U!Sw-fXoO3z`n5E&>h)rjT}%REqftj?zt08he|LwZeR>VU&i&%zjPznkMTUO
z4X<YIzH)@7fCz47t$P?Piroc*`_JFI0d+hZRf04F`Iybpo;tL+J(M!yF^-2AJz>(3
zxAkJR0-L~?uxWalDR4sJ9L8Jmj`{s`kUkAxF{stXBVOSydbFSj-*OU67j-Y7^tFnJ
z0^D=i$&X6uXnxMd2%6~&mx#N=C?kq!6h>kI^7NPt4tf%pYkC(Xu23yc1NQx_i!Udq
z5H{@<&0Q#K>ZG5G9}CSQBHnJAtxf|<aUkn~qWg1&{$Q&J-@76Pg>KFy>Mc-?Pw=kD
z*N9U#+6VYkKx`5~RV2Z5F_{S(F)4&UM%v;^bQF*29w?K<zysKOn+lo@vEHRDlnqQi
zD6w9Bi_y!8Ibb0#<wqjAYq*CRY6HFq`CVn>CKaX?7@^Aac#2Bk6+;4Nq5EN)*A;QE
zEjTT#ig+wO4%u;(5_JA$!b#*TId?2j`6Js|b;y2@%JFRy$NIX|{`p#a8h_0>iD07=
zg`3J;{MD|0C}r*ZW1KzH0maQIR$TZA8hv|`E=%cDH;TZh`C>*i1q{jyb-_!(br58x
zKrO`IvOt}qtVsnyBY;SS=!KTX;ix(AqAW)Py*Tj({`^%Ib)*I-V_;iOb(f~J*BW}R
zx{{k3nH|Bz<<m(@f886jJ%FAy%Ua2?6-JHN5do}H*HS!>He7Ho@Ts72xjDWgFY$$^
z5bt*q_!}>)+chm-SSUo{GxHe$mAFAqaqjC3jMAL%6N%TywmPVR7n#oC9gkkE<D;0F
zdyf7}%S_p1L-2APBtcda;^LVHIB|v32izC0JysN1Zj9Ykq#+8QP!(k#WIf2W%{@p)
z&4ZAGBVEoaW;qdTK;`}(J}@=<>i;(8P=B^2IV;BZnwns?wK96up%R5~+R}J?6P<{I
z?6V%m3##(d4)?FNS;lY*ygniJG&S8x;Hx|lU*jv_Vg)itZ!QX&|1J?M3g3t(Wze8R
zNPN|Eab=(Z5$QO`>zRE|5FSNMTcy3}rNGqQTQ2hd8}R+p+tnjOyAL*UV(4D%L)d|X
z?G7D@U=GzR#slQ%1@z2(qL1=Yr!NuwC0rE_Xx(v9$TK*vEa4?YnRJ8###mqa)wnSw
zvm)Z+R%*KI0V~Az#IU8V-h(aglCI<O!%_sfn2-v{o+NVc3C-}1cA=}Y%L?NGTj8#B
z{&r%gYG|=$l!)4&5^X(u5J2b+h><PtpL$x}%<?VG9O}X$41dzDTNa{g?yyS@eCj)O
z#0@Y`ZKfR-(U^$r!PB-byXA5NW-&smF0;9bb`FLs{4`G@`=W4V9a%%FP6za2v6pFK
zi7@>cJ;sS+QwXH4R`kk>>&rzLCXsv-Ed&%a3h>S)#KD4HSB?|5?A<ct;Y(Q|x?kSZ
z$=n`l4+PGn+8WwQkqQl77x)bK2tf5XKP+j#CbzCEb^;~V&!!^}3gd`zy`Yp>hp{Au
zIlo-CNKHc?B{wU1@<|D}YY`M(oHWQMK~PD=nd*AUQd0SSh}v#JTqMufKD7odDte*y
ze0aO{$#rs3U1<Mof_iCkqZ(%*rR)i~o1nNXs$|Iw1KIkZECOyxflM|HPp)s0@mGXU
zHvF=@p69ewsRPWhkxxr$;5pv7%Q23>nNs+a21Y+N^QIQ_xRmQCfFut;o2PFZ)HhF$
zbS4L@?N;cP^QXQ%g|v&?y-&)^&yjUo*^elb37|phOIGCQSr;Pt<-9AGnaefkmj|Ad
zKp#8drCV&Kb$k%d>%av-@AB(8xJ8j)|BY@Si^AC$@(YWs6@zLLEBqU0=*d47*6Yy-
o|It{JoG9~i&OzAR+<kVR@tZL=wMQLE|HvUm`eu6NI*u{_2XDY3n*aa+

literal 0
HcmV?d00001

diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..e9d1b55141eca708c87562823c29c545c09f010f
GIT binary patch
literal 10512
zcmV+rDeu;aP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00004XF*Lt006O$
zeEU(80000WV@Og>004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000Uv
zX+uL$Nkc;*P;zf(X>4Tx07%E3mUmQC*A|D*y?1({%`gH|hTglt0MdJtUPWP;8DJ;_
z4l^{dA)*2iMMRn+NKnLp(NH8-M6nPQRImpm2q-ZaMN}+rM%Ih2ti1Q~^84egZ|$@9
zx%=$B&srA%lBX}1mj+7#kjfMAgFKw+5s^`J>;QlP9$<he08Ca!x?iw+2oTB3&4r#J
zaspoj0q}ZQyaI63&@+He2mha>S?PR%=$HTzo3l9?ED;xoI3-JvF1F8#m>QQXW*8-A
zz9>Nv%ZWK*kqtikEV84R*{M9Xh{ZXlvs2k(?iKO2Od&_ah_8qXGr62B5#JKAMv5?%
zE8;ie*i;TP0{|3BY!`4?i6S-;F^L}%<Raqb0N_XoUvb=5EZ}4d#FuhOOV8nR6A}e<
z9hNTL)Y_Us_vB=ya0CLw046J$$!F7D(o)lzyc_@)@BCRZ;@Z+hMYc4xwzM=fGcx_E
zQ2%xFZ%W+TMS2<dxn~fq|BLOf{L&f#V9beXv-68Bt_pz8Eda>f`(o2L0Dz>ZZynda
zx(`h}FNp#{x{a}MR#uh~m%}m=7xWMPPlvyuufAs_KJJh5&|Nw4Oks+EF0LCZEhSCJ
zr)Q)ySsc3IpNIG#2mW;)20@&74xhslMTCi_jLS<9wVTK03b<)JI+ypKn)naH{-njZ
z7KzgM5l~}{fYfy=Kz{89C<+lE(fh?+|D$id_%I-TdEqLPi*x_)H~nY9rQ#)noA5c#
zB`Ac>67n+__r%W<paB6$0xFOP%0M0H07GB~tbi?W1a80^_=6A-304CZNCc^X53)cW
z*aQkeG1v+AfND?&8bLE?1;;@rI0epwOW+!~0d9l)U=&P%XJ8h*1`7}bVIeX^f#e|-
zNE6bB%peA254l0UP!JRe#X<=X4-!Io&}OI@Dub$_dZ-!t9y$q~hps?_&|PQ@nudOd
z-oXe=f~l|)tOXmx4A=?wfkWU`a00vr&V>u$9dISw03U@r;Pdb`_%=KWKZEBGfDjQH
zqKX(I48#TTN1~8;gpaI8ijWGV0cl0Lkv`-mGK$O~Z&4T&1w}_0qHIx~s8AFOwFb2w
zRf4KU9Y%GadQmq~W2jlwM>H9&h}K8jpuNx$=mc~Yx)5D~ZbG-CFQRXwC(y4k7z_=g
zjj_UbVj?j~n6;P^%sxyT<{V}aGme?VVzKgAeXJeUAIroFu!Yzv>{0Al>=1SW`vynE
zso>0T?zku%50{Utz#YMz!42UiaSM1Uye8fT?~iBWbMU43MtnE^I(`DbK#(SA6YK~f
zge1ZyLM5S<aFOtU@RCR*su8V;fkZBGBe9ZrjCh$iMtn<>A?cA^NYNxAX$R>L=^W`U
z=_Q#=)*?HSqsRjC4stX30{Id7jRZx)NWx2kEwMqOMxsMvNaDF9UQ$!iNpiJhu4IMe
z3CZh{Gg5ddEh!f%rqp_=8mW^~BT{qH6lqgwf9X`|66qt-SEQ$8urgXQZZd3{0-1v{
z7i7jM2t}RZLSa!hQyM83DHBu-Rh#NXO`;Z4zoQONXJut%m&u07X3N&do|YY@Av7(T
z7cGTWN;^&)roCIDw8Uu%XUX;@txJZM%*!p6bCl!A70I>9-IjYNPnUO-PnO>$-zoo4
z0i~d)5U7x)uwUV#!pu_YQro4hrA14RFTJM-E9xl*DXvvKsMxPKr=+app_HyvrF21Q
zMwzDUsGOu+u6#y$T7{xwufkO+S2?TllrBqmqNmU+>Amz>RYg@#RiSFV>VWEknzmY~
zTE1GF+Cz1MIzv5Py<ELVeO5z7!%rhmqebJMCSH@FnW(u}vrltgOIs^kYpYhL)|9rK
zwwHFUc8m4{9kPyt&KjKtom;vXU50M5?mpccda#~_UZP%&-gSLg-%_8ezfXVA0BvAx
zz%ytt7%?OnIvHjfwiu2X(TseJ@{Kx;o*QczM;Y%j?lb;qVqubE(r9wuRL0cXG~cw_
z^mj8oGnQG6*)4Ojxx4uW^Dgrj%k-CVmhE45$AV(vXR+0y$Kr#fl_lS@)pFWO!z$LQ
z)@p=7Wdtxv7?-Wl*3Q-&tWR0LwXw7j*c`X{&DPL1+4hL-)N<|RoaK$n$L-YYn0EDc
zqxN+BSo;I^qYkPLOos-C$BycbY{w?YNhe*WB&VZJ&z()2`OfXm^DZ_n>s-#cBCZ~;
zMXm#GGH#)6)ozd6)!Y-@Tij<oEIihFobyC``grd09Pv`}VtF-t&3apTuk-HpA^8OR
zRQo*k)$`^1cKgA8-hR9N9<0z@!CTSk5B$CScl$pK&<<D=@M9n*Fd(od@JWzqP+m}9
zFeNx9_(<^U5a*E6ko%!Jp~BFfFv+m!u;#G&aM$p%@X-k4h;<RyA{8RJkzG;PsIaJ}
zsJWGHEBCCNh_;9>j2>R4y()XvmDLKXQ&yjjk&I!+oQOrohQ}U>eb4k~HZbSnyy9x(
zW?3$*y{u<!M|L@Tnq$W)<4nfe#h1lTCD<kGPMA(~NUTVl;kt0Exi6ADlj@S@ll_wq
zC4Wi@PiafVrN*Y7<jL@odA(`MY1wIm>H6t~>7#3G*6dj`%lF|oWk4CLGP(p*(a%)B
zP)E2$IF@OjS(EuDD=h0owsbZxyFW)SXM4_Mu6ypcYf)=iYkTrk^ETy;t#evezaCm2
zx4vhC`i6oH6B|7?9^ORQl)UMue3SgL{8yX9H+L5(6>KaR-{P^QrBI@fUpTVWc5B@>
z)Hd$6f$iqotG0hEVi#R4HYu(seqX{Wx%!RiH<jOf+7Z8FpwzN-|4z(K-p=7&4!aJQ
zNtfl8jqmo`-BC_2FDievCuYx;ie(jbdkK4mdq*pME4!*Rs&-bruTHGKUE^HSR;yUM
zy>@;dd*9H0$NjB!N_E9`?+$Pe+^P4d?`Y6!s5po@n0fF?V_0L~w~TL_n-rRgn?4-k
z9U46xbhx+Ks=4`y;*ru8xJB49eKh*$jqhB)>uNP@t#6~X6(0k~gvXwKAN&3Aai8No
zCm1JMf6)A)ww=;m)B$zmbj)@pc8+#Mb`75NKH1Z4+ui=7(T|5tsh+AiEql834B<?{
znNMeP&(57oKR0te;rw_{Owaub5f^Ut2KEkI^tpKXlKZ6#eNKI6FWX%{b;ah&$*YX3
zo!2a{b@W^GxBq1EQ~QABK*x2f>s>djZ*&hXA3QVUFm(Q=>&;8Iyl!2)z2f%ZaOm)z
zk?4`pJM24CcT?`ZxR-fv;r_-4=m$j)r5;v1Qhe0#v+mDrqn4wm$6Uwy9|u3aKh7F|
z_DjYu?<WeLke^gcs!TRdnN6LVcAviSbmh~DXX(!tW(t3m{<ZeG&hsCBbNsD;Hez<-
z1^>mT-%DP~zdZD6*{hzpfVoGnQ(rI47rl{xbNDUeZQr}_casZQ@3HSIKj?nw{^;}Z
z!Kc(upZ)~{nDhK^CfpAI000SaNLh0L01m_e01m_fl`9S#0016KNkl<ZcwXImX^<S}
zdEV3AbI;D6*u?_7xJiN(0E#ptQbkIZ<g1Eu5=T|3ieu*}o2iN|$#h7GW%)?TKWtao
zmdi&uiKWO^NkzhnElMI8in7IsMez_J03t{L0thZZV6pcx_t~eP=j)jzz}b~)|1$k9
zK6Foaf5-d0_cuLO6h*Ks3nZH@(QOW!E}9$fV2ZjeVDq~zWP|t?^#Bm_X|_Du09%Gl
zK>Tw6KuovU>TC_R4qNzE08%_3WSeB$&Nj@JWc%j;fX7y5TV`8gtFpOo1t7=s3AO{(
zlb`-dHWLhnVSvc@;dR<ZXPiU|K@cF|wI~ct3(PTq+it>ZyGZA<9MMJ;goIfAJ$Rmr
zWI7AmarjINVHokbJOZ!7u{-8m%M3#wHv9S<-?nXpJO;d$Vqb~DcRi%CIgZWiegG$x
zMBr-dl(}a+R9MdG^O{*J$85LTTw4dFVyE^a4?X#_WMhVHfvrlu4FWv?3Ot`;JLI4J
z-7j|rKFE%3oH~9I%ky(63=ZPvBZtWw7sv@h&xcROv=CoR5`fC;ngJl4AK>B%R7l`?
zuT`%hk;x)6P(Y_%N2^xF;I?rx9H6?kg2B;oBvM&)T6H9n3A7tc9+U7|Z35mwlK0Z=
z+pLt38y<sWTUcLO#KL+NjYb0p_U^{m@SqWn>v=f;+C^9dW5@V7!Aql7DdW)ob=-E}
zR~{gLud=<ywnDz88OHI6r0TNyqyQ0v-+l2VeD$ek@Yr)N<J%|C;MG&F;NqoO{MF-s
zi(0*bXI?ykV=tefdkOKqb2B*k+8boHil<*VL4gWX8&{T!c=7Z__>}aM&m1FTv^0%R
z$tF^1IFdLu0d~SHKw9Mx<R}VZQ^Gc#b3mr-gkvNeP#Xh^_S@fk4Ks^HEY&@H`_ws<
z8ZC6FUEe!>o|3mPFpxu$U^jTp;hZ)>BkgC~!`3rzL)QXeT1X^4w}Xo_modLq!tI9-
zVs>dA7cbA@l{4pY_~3qAU0gCuwz;6=yw;)mI|-^SwIV|)DyY1C?jrW?+>Tr}gI6zH
z;UZ*4Nw$PhSxqOVJgO*X<x0pbwZdV4X;6|{AP@~OG>2rjUzOl5R-5c&!Q!>^^Q)L&
zS;tzrYWjTR#5tUwTShXI!s2?FV@AfLNZYziPF}(`)B|9HjGa>hwvCM<&&6MzU&5ZL
zNut@|8Y6u7<+B(X%%fbX8EIOaKvZwG&0^n}Tf*h}Wn<6Jo;VGk_Z`PVg^MoNnucjf
zOMN9BnG{8D&ZPl%Dn82GYy#%f<~^FD#twWJ`AibS`3yX2-s}?1j@nV7*+|_Jwu6KF
zcH-EXi+JkAQ>eE(#!S0mUJ*`B(N1CBP|pVp@q9Pi;l_#IJX*EhgZ1@woH>0C7YRT_
zP=+|^p6N+UO-~^rKmivf$w*pJ#3NO?UM?e%&LK;m!BGv9HlJ(KG>8Ing%R3#)qEb=
zz5@Y4t<VpQ?3|*M9AiS+fdRBClqQ{<M~Szab)?f7<1Cxi3JRlRnB|(je|Z7bwnv){
zsA&^8uzLsAR*N`$Wf8N>>zvNP?KkYk&e0JZIk1L9|M5#tkiVDNzQy(``7ZI;4?y+U
zZyYTJci_s|FBzv&X>`zRQnjfxnUsYTRaAgTU3Cm8J$Zda1CP=)b}VV~PXMU(o^z<8
znom9<L5Wd`;dWY7U7mBnA)Tf)BqV4?YP9Dd;59y%Fy7vcy*=+$sx8#o5$}f>%qK81
zkTH(6<waO8$B}C=m%!BSdkN4S4*l$3zC8fSFZ{~UHTPC5%zPD3e&HCO&|{=n)BDIU
z`cIL#tUKPn4P%oZ#?FZ=c-PN7vMB%?&Y(wb<toF=cE(sGOc8$Tw-}bj=`<ZCQ$8i=
zG5)sb^s)o6vYbWXaIuMx{%L?e`|K|vtbEo;&!z~Z6%lROqVy$giZ7mo^7*g-y^YWO
z@%>Cuj+!eG^OeY=KL{9+{RV7JpQ8P{d+^JDG=MLE^AdjZfsf;ZhhD<Fj!>f-1z2ep
z7N12S#LS5be&<scadI_<N?{Z~Jzb@Lu<3N==z3D@r#>g>yGm*rR9j_`q^o3l)k0Jw
zM>PjQnQFU06<cSr)1k^YIe3-Bcr*k01hnbBTTDdC{9NPI4F^`6_d5)4Z358bd6P$<
z;JHlE38tFWpxRfdjaB*<`d5>$c?r;`;>t{&>uO+XTMakwW<ocA5%z1ZVf7oQar)>h
zSoq?3+>rJ0$@?d<dyx5rtE|_kw=yhQ%$C##fNWT{tY{#zN*?^V4*YcsArnfcnL@Ib
zLA26ANY5X&I6<2Lks*PmbF0djy+#1)Ja2G{27N-4T4aFWY6OJOJ{|U{bCEU9Wtism
z3Ps;w-<F<ru)N$sxlW(K+q)(cu-mgJ9dq#)M}7R#qj%w<|NnFN?WgX>cb`q-UAN}(
zZ-0c*tE0@9yi<!CYYXsdbLR7A)CYhZkkVJ>1EPQ)-dau~vBHF+NM=h6VU!ZqX%bX7
zt4OC<<MPOqMNP2k1Z6%zVxEaiQ4CRY)>Ckone-HSuTJ&lwTOa8hxaIXG&xs;CeZR=
zQB#~2$D%_7om|9RqZzF;EJhd`VESEh@R?)p!Jkw=hAUG)fyBPs@%*+Q$6sCe02=43
z_*ehJ!p*rj&#@RGm_5;KRRe8K{Q%Hz<(ZX}8{&e^;%ZV&hQEpnS6;U0!yy1zpp=(5
zjB=AIrMm1PSYpn<Dv&7cBFCUM1dG&|6@p3EW0ly4(zjY{G?lPOMrm5=A5z)^BIG>~
zYg<6@+*E4=0p76Qjc1cTgLeHQqS-&g_`nM&)czVT&Rk`(HiglN0`9#-F@W=MdS!w7
z+lu-CkO`P#rVD^YH4bWA*gAbdIYl#|bZT6V8iDYNEqEoWEqwqwbb2M)`YQYJS;)_p
zIYp7x^*XOpTTo<ivqlL~y(9VpjcHYQon~XzX<B4f{w8b?fF_eAj_C##Q)Fc@K4zm^
zFmI0_Q#pal$4}$S4?l*vGtZ+&hgS_p*r$k}yhFJTNj`w|5B32Ovp2<gk({1ip^v8e
ztA&zOjn!Q<$Lp-NN=;a9h8ZDE!KH&V_AAx35m0l2CN-zpMv|(Ypq7L+N|ek+J^^F1
zTsE450)Q%Yo4{DK|3J>N7NI~lo=eatF?aB3YPP=zj+@8S<UJUk-iboN#`dX?VE5=@
zBy+TNdjR8mmG;Nvuz#EhZ%%!;WCDRtHSB6YvQAs33AHKhPKm9^#n1=%^w^zM=KmEs
zxDuNft~>B)w{}D)NXFVNMHGV6TsKZHp&EoL?K1<EhM75-K}ITwr0Qz?r)Ie_3!eZ4
ztS49vQp46NK1PPKT+0g9)3+jb_@lVxmQTVOz6%E@uHwk;IRty|hI`~5vvvhnh2kGz
z0sR2@%>J|o(DMPE;bDZM+hONfEjxp}&QR#25!z{bR~wxM%UXs9LPF`Kk*SWrx9LdJ
zVvKcvJxw6899J4a@QTdV*6MU})FhW#pFpG2b6WvR;x_7x5-sK%(hAR`d3XaDWZuvU
z61Z|Tz)j_+@$c?=4lAWoD9^D^V;(=e^8_CFPdVgn`4Bn>K8$G3y=Lv=Toq-4S>{&M
zmkFN#+<T8+xVjG=_bg64SHxnY%|TS*(ZdJY3!tusN-a33MUT$XR#D?P9o?_q|BHC`
zk<T-&Wo;nWlb~s^fMQoBIT9_ecZ;WEiy?mffnUJ0kA6;aLdfShFpu;%)D?@SDAn~@
zD!*{KgIPMx-}u-s;KH~59O>P|sCYCtnqDe9gpr{E)(!+yJ9#XiEIWnK^WVYy?#?5X
zxefbvU%^fP<)ycm3ZMJzokw4v+mE(;1}C2{<AHzq5j{rfhe#)5g<*QmCG$K>CV5MF
z!~a{3@R4b%Ame%}<<KX3XmwQg6DU?}^2=e!T;6zP;Oomierj))nHoRwTEsBN)vz(j
zI9YfsvTUZ4UMj*dCPU9%aB=(O7=E0qEQ~l9JIIsq9n2Od*e8oHnK7DavQ8_5U;n`E
zcs~Jfl813%-~5&UD8IOlLPh{>d#T6}EkE)IY}#nT>LAB5*o!)7wdEikR&F^{$TV9;
zeDiXMfAfitW96?uhirkB9Q(J+E>bL1oTU6p2K8DE1BEo1_VCRa5BGlR7g2nI8k1t|
zXOU$m2^1OjSotM}=*bH^QOxZ@WfAzl4?l{Z`uzXI&S^qVv-4Xl>lu-vVF!+4q|eZ8
z(;-Wd2ttqa(PV^MP@fMljzirxIwdI$+PdeUNe9>Dc{5C+5hT%O*5}gswN#Zc6LeXL
zwcFaWQ~x9-nKRPl<7AL%v(~qh5hyHzU>n;^XHrHBEK7<XV5Go0W2l2g4)OHG75w?r
zGkEOeRl=Rd#P&&~-hB|(E!)fvW-vfs<uGk$?rfn!Mp?ILACcxGlIcm`x*H;!Qr{if
zsA*jk+hU4f)Pe|Am&^uvxM7;H*<mzGpu{*`cUd5r<)@emXs0N}W>X8=G#7&BrcCWl
zycpUeRH#567pcvTdb2|i84)b{l6($-voeA|d@RJT{jVl||MM$&{HYndc;XVD_c1V>
zr#u*W=v$D;8U~$^0MN7|hGB<m3u*sR*XN0OlLM%2L45$Il2eP7hf#pBI-(Pd=>2`>
z{c0hLm!Q!?oAJF>Yaw8cA2C@8>6m=la-~y8z11)v`eeAx`)!($m5!MCx~MUxyL6;Y
zKZ|C^Qxb_Q$!++;*#Mt@d<jpV?cl0_%V#h!ltUr1Fg!Gf$>|*opL{rxMqo2(3Z?rb
zZK+X5Xp|;81yVP2U5YF|dfMDi{Qz{2#%qxpUY%i%F_>^K`Aw{H@oV$}MXGwE&G1C^
zr%9sC+Mz~g*p{>jOsU#Jl{bpDDvCUBxoI?73A9>i_Q_D94od+GZGv*i$>V<?Z{zdd
zwNRsNhp8kJ#SWSDXhI>9`2aWHaw7_ZLv*+dxLix*P*CEN(pJfBq^`|RnjWZ`G3m47
z(bm)lK&1VA19Obp0<*eBrliGA66^I8iWLjhij6Yc0(E(rUVnv2QHzOBjer!Z0ZL4r
zYs}=ztnw;l<_RpLODvSu%N&QPb*Y|U=p-Xy8y7K*htHJo!i753nMD)TyP2l>B<P74
z(zMm~k$?RmOz)a7$&*8$5>W%JOpeYoK1Ygq37-vYGH+80tk?#W1DL%DqtTmFzXoUn
z;~LD4-?A64?w!EJsbS1ajpD+#9A+l+xI8(Cs{?7OZURem!yTgDpo3hd16-oot<u4*
zCsJ7E6pOq!$9q@kFD|!T9$nO_Rg2Vu$Ib#LW^!h`%yO0(Z5aP)&sIRGwwt);&I7pr
z{{LW{q}18787Z{$oXpV_3iJsDf{>>M$o_MDhCV=Em(;W5tqovP0GNyGGVM-u`G!fH
zyJZJX9@&9Yw@u;no%?Y5uKhT3*8!YWyK^tj-mwd%@f;R*4dIQw+c7^iiP`Prcw=k`
zmxc<MV|lv7HO*5n^Bi`LIYNaxdxnM5iCKnNn~P_1Q6_jzZ3@vZq^TWKV-|kwM{i|r
z!vsp@xk;*QvoB~7^oV&s%y&BaR&RjoW{4%Xsjdcy3<kyzY)<_E2sTPj9#-Vj+q(>b
zZKkJfD~&q6Y?*4ep2}b?lfiOf0P|ymsOM5x8_DCfgVVTh^KP6!umk7zP2%;vlen~N
z6qlyQFgrboxt&wE%mk)P$6Dmr>4^-|+XD<vjbP^udoc0tG2DLlB;I%DFn;phoAIv0
zdyr1k<8whuqEd8nNv=a)KZ?jO3j91orbpOvND-KjenMm^=~6SFHm5!SL_(~GnGz!<
z5{??fqs`VkkM)b*(lqr883set=|^ge22Cb7<&1>|CPP=599<nqVYWa`86HBIPh)I%
z0SDf@8#msw4>!GUKW@BxFAm+k3rF5}0}kAN1Agc|@4^0EdoaXE06IP9)?_G6GZ`fi
z6U<D<nM)LyV7a(D_Xb{i=|z0uFCNB2pZp*3;z{N^h97`HUnUqo-D|+P@0{Nn!D}?D
zyjsD^l~ufc{363&H<=>o+(Z<EReV)iRxh`(I$y@?r)H_rlmo9tnwz=*Xd#QCY!a`(
z*2dSLK95W;ix*xzjYl4N0^fe_89LC=<PNo39cycAJl4=`GAy&oR1&5+e(t88BQ%FC
zslOKZKX)BHe|axM)hWDktby_We1H647sl>^(pKxnO49P>RZQ#|rvdXi?N!W5y-Y$S
z1rZLEhL$H)USFzU=Omw(xe)+0oqG&>lfwlZ+%t`l!2;`wG!v-^U;p~Exb?QfC{?Pc
zHEL+pS!-08PpFhOBBJwD?awBj*1q;>{OE^<SeoC21N#@S@8^%by;?vjqi=l-jHD;N
z^?0lg8vw*dG2-*t?gvVK1`mGfL44_%uOXszY$i~0rw+rTGBq#qOok~3>yX(i=a=x%
zL!ZEtfBQA2$MWiw7}Y#v)i^#lhBMpuqO$H{aixvwdL8G^9mfNo_$0pi#8U{khL8~@
z!+G@;z2~)&WYMKBS1hL5lG6L*mHoZc=L5u^BxFuVVuG_6iHZb(5SDLHz%+%iLMN}Q
z5J^Wis|PwP^^@e;N5!#@7QJ)GSg*oJ`Vlg;dD<Q2cnL-Yo2ho9K84jQX}s|KRh<6*
z3YJ&uOq$~F_oPJ@Ge~*?WHZe8$h519k?UoG%EXH6Vmcnsx%NoTT;Ee}MO)u_3-xUJ
zS`tPEC#{T4+9R;^c7pl3jHaOQB`dI)3z$YYEZT`2t4X@J*oZlN<d0BuwxQi%QKela
zMw^(ZIcgk4<9lAqNL=4X>IDjO-C!NB(5L39^@y;=>)V3*05B0it^4`!Bclymm^pUO
z^>&D{{oYtw4>cnmlmA;}oJ+HiM<zLmWP;UQ$TZi_Q)1MDq+pfzwvc3A?<hCnxtwK!
z8K1recU{kntx8W{gsOzs8zHS$lm4q^W)hi7kbSqJO*KGE>vf4Iju&8<c}p`48vyil
z%%V0_%?L6jwvFeN-32)&J|kRo9;w7QnHyt@8-ES%Bv{I(s3la{9;o{3?ILM-^ZE?$
z^%xWL0wj@8zc=UVkrBiXpgsUJh!7VHq8|Ehm!$IAOc4m?T?00YcB)rt!XUwrHo>Ci
z0LRTyY8E;ziz*!ufDVr;jn!OAIBq74it{e>BHizeEnnn$9<_#JGcgk&YCTeBE1<Tb
zO*KIAc%zG|E=sWnLJ!>-?Khi9M?aE%QY+{O;%}F<4@f&_+Bz^eg~6dcWQ1ue`)kX~
zabym9o|?lxKKt~-s~GmF+Ah;%?HL9%El-=TX*yFTTJmiH&B@ZX8t?luJ+Y*ss7u#^
zu^DXwK$jWwKS_)W5W{e+^5!!CB9^loO+r#9f{;*LXE!|>Q0-HxF-%V%!RXj7O4LS+
zWi@qz4A6!NaI9qsV(l1J))IOqpf@}`nuk7nk~q0mROm=U2#zrc&Z~DB1fJqn#5p#|
ztapQ(KI#KN((W<*k0IOAPO#LF&WWBpVKY}}+8VlfH0xr-<$adIT)a=!?*Xc5HLpI)
z2S{>aE*^)VkOy6-kWIFiU_FvxwaKKMeKnt)B^&#_b?Lnjz8P(@D}2|{b657F(|#4F
zj@9t+3Kz%$%%2glz=@@Ot$(SkRq)Y|e-vLl`bBfy<N;imWlB@orjAnYSjDTwRebE@
z_v7J5zVzmJ{4?Q^f4UIcKZ*CN<#n3RD9^8Tf?9*(i7pd7h2CzT`)-U(CYVnj!qm=L
z?EU$-y)DjEcy>S9ty2bo$@?DQBpjF%X+bf%=09GGkNUWLc?ILUw{huYkj~DIk}Ov8
z@U%%v5FB}Tn`$pGX(r2aSFnA@J~Ot78fIXnN4hV}iDH+3;rxex@O#L%^rGihq=&of
zA^rO!;|73%+^yI#@dozY_qG9e@6nn08_{SS$ICC(@x6UFGD(pGiWh1eq;ZN=JKC)#
zmOY<8c7dtzC-B7Id<C5b)ixSNE;C9nj9mFV*`VsnF^0a4*Uy~9gAe`+9)0W^9D}2D
z!Hsus<ZEOex~_f>F28<?04(CC4~-g?*JBz>c|+Vkt_4gorq6u90Fb{8ljAekf8XY{
zK)(-QlX^)ChIGPzmNwmJi`st+=(IxGpT31*F>dzeES0Nzp^>R>qv9e(>01s{UOl7!
z9=*PorngE_D`Jh(WY_u{O{KRyBQh9JyYz^3LeFeGrf06{)6*RDOnm7&(shBm74-oi
zc^O-x<jiM|N=I%sA#ElcrjaR!#fwdkt+zOxBps5ILfXz?ZKcfk9WpC(QK{&>V;Ixx
zugc^EZi0QZFeNy>crG#yj7Lc}c7WH%bdh10{|r-lSf4jQ=`w20W0JoRKU-1121vsC
zmR71q5&#BWF=`g1Z+aN6c%Dd5I_VVbOxAd6x8c##1EV98Xw*9BuqxD2(t7RHXqDjY
z0&Ao~A1<ajzCOpGC^v}1Va!y_gn3-F!JD4f^1EZ2G2%PdlHNc32Wf!D(yOw)(IVNq
zLXo7+Y|BVp$0V62Q&M}2(v|7eiZx_Y1zyS`pQi`T4Ir%-9vP!sO%*XJiF?xEvNZ*p
zu8CQJWSHhP0~VX9G~*7W9@DxX3r5dM`Qxv|^xyTQv3p<hZAN_n7?027qo<aVylQoe
z(zexDg6exb)!q!jCJVD@5}g(k6KX)hN^??eN?3+@sky6nj=GF*FiA2whfGVRq4D@J
zAQL8|69D?-wQHAedUhE#{KrVdt#{3w#bh$e>#kf+{Q#%~6O>+;NZ;<J_?SZ}*#Scv
z86(_DeNG0vMP@tNqH?J%ENZM2Gc=c3Ta%8Apit^^c;=6b74rf^O!+i3LIa;5FuO-f
zFK97Zgaq2>v;o2InENyz!yv&n9C949I{hDyxxuzM=cg{<0yKVZbJ_%e5Y0xz*q}(|
zr=(+ES(obfBu43(Ysg|@zC?{7M*Qq6cW0Vvrsce{L5(30bg#o=N9nD=pstxY^q@K8
z^X9q$GA+&&rQ$utL<UG{PnWLaKR(2LNP5HE=X_gH9{`%vqh#c@MaCiVTwh$s{v)NM
z1R!KjsdGS4EzQ<AP=cW^O&~nh^}Z=ldydbng<7MrWLi2Z-m4i^7n1@(=Uo7LM?EW3
zQc5f`&&2SW`#t2$HO|w;A)b?@qU>7m-b#G{=qsy{v2E-V-x3p&tfVc}rHV!!8LMro
zd}XbQL_39)lSWeEQ5%zDoP8y20m?O#;zh)uylK^Pa$-`<NOMHeKGUReynkIpFd%9E
z7%+3xbtMe~!W`cOLN8kM=H86@GQm@SbnDU8#+@jYzk`$CshEe}siaJ>T-k-24lLrf
zUw-B7rNZYw^WLNLrFUa}?Rf*7^gv0T5jxLhdfI-{PhB$E9Q{G;D`El3UgP_cL{hKB
zD?agGz(}CY37HZdjrlQClKDYw7W&dtN2)vrkZ&+W5yvpUAEIU?Q}G_5600od)f_T4
zZGz}rlgQU-<0Y29Wqz!&TAIe88<%n0fBV4z=*u+&z@;yI;4d#N95i;R@7?80q_IW?
zwJ0)DTw9@8B(Z(>H0yKPvYz5SqwanO<x&|#BV+Ne$Q07pr&cOqaD1GmM22b=CQ4O|
zO-~~tLjoh6&6;aDGS|^B)p*^}uR!>GwN%CSsU28bSYm3Ozy#0N=N6fUJDg__jrAhZ
z`Mfc|1~ai-nm`bRYQx3SQVEA|Ud9hS@ap5_uLr>C9soTbAkYLO-M3B&3fo2sLa{69
zkuV$e8Y{&%hUh2MU2k)VdG%ADX02wj#F%*j$ZL%nQrfPfH1!fwtKL8^$6A5lbr?P+
zU1guiWC|UIP0g!ci)8Wx=rDoG4;GAev|B9<4h~WaJfk&*!2ub+5mu7^Lee)&j+fKj
zI_s9sR6;g6A2GN=Jq^(B2FKYB9RJe~KRPjy)-S7i?3-jn%!iz~*=(9$Z{!9FhMD-j
zCZKk3QF_-elcQ-+Qsx>Lr{4$aH-E|~^>U=!qWKi^W;s5ihF-KXzxOjt#3i$wVuqPy
zyV>B8Wi_3%Oktof7>82Mm7&x_mm0>!={G~VFU~bLl@SfDMO)+x%XRld4?g)Q7xW6-
zb8O!y-{zI_9sn}1-Y-Y@vK{C)iCI51>S6ItBS~A5*H34)nQ)HnINK%itzRT;03Z<x
z1pTB;Oz&iqPmoqfJ9?(_P9p&zHPsi0dT;$Qn|?jIOuqGM(gpxJ7n9Ok8m|FDW}u^9
zy?!TaKu-(Au;RLaXp(Qex_TV|J<<mOp;S;u0rO4;phrDTkfS&6?2>O@1O5&NrYr5~
Sk+X3C0000<MNUMnLSTZA#~RWA

literal 0
HcmV?d00001

diff --git a/main.py b/main.py
new file mode 100644
index 0000000..ca66407
--- /dev/null
+++ b/main.py
@@ -0,0 +1,866 @@
+import win32api
+import win32con
+import win32gui
+import pygame
+import ctypes
+import json
+from tkinter import Tk, filedialog
+import numpy as np
+
+# INITIALIZATION
+pygame.init()
+FPS = 60
+
+MAIN_PATH = "C:/Users/User/Documents/Coding/Picture Puzzle/"
+#or MAIN_PATH = "C:/Users/RVKG/Documents/My Palettes/Picture Puzzle/"
+IMAGES_PATH = "/images/albums/"
+
+DATA_FILE = "main_data.json"
+PUZZLE_FILE = "main_puzzle.json"
+SETTINGS_FILE = "main_settings.json"
+STATS_FILE = "main_stats.json"
+
+# Data loading and saving
+def load_data(data):
+    try:
+        with open(data, "r") as file:
+            current_data = json.load(file)
+    except (FileNotFoundError, json.JSONDecodeError):
+        print("Something went wrong with file loading")
+    return current_data
+        
+storage = load_data(DATA_FILE)
+puzzle_data = load_data(PUZZLE_FILE)
+settings_data = load_data(SETTINGS_FILE)
+stats_data = load_data(STATS_FILE)
+
+# Configuration
+SIZE_CHOICES = ["small", "big"]
+VERSION_CHOICES = ["4x4", "3x3"]
+STYLE_CHOICES = ["classic", "original", "sci-fi"]
+MUSIC_ON = [True, False]
+MUSIC_CHOICES = ["funky-leap", "serenity", "sunny-day"]
+SOUND_ON = [True, False]
+SOUND_CHOICES = ["puzzle", "wood", "metal_pipe", "lego_breaking"]
+DISPLAY_CHOICES = ["time", "moves"]
+LANGUAGE_CHOICES = ["english", "russian", "latvian"]
+FONTS = ["msreferencesansserif", "arial", "bahnschrift"]
+
+if settings_data["gui_style"] == STYLE_CHOICES[0]:
+    FONT = FONTS[0]
+    STYLE_PATH = "1_"
+    text_color = (1, 35, 61)
+    timer_color = (255, 255, 255)
+elif settings_data["gui_style"] == STYLE_CHOICES[1]:
+    FONT = FONTS[1]
+    STYLE_PATH = "2_"
+    text_color = (255, 255, 255)
+    timer_color = (70, 35, 0)
+else:
+    FONT = FONTS[2]
+    STYLE_PATH = "3_"
+    text_color = (255, 255, 255)
+    timer_color = text_color
+
+if settings_data["size"] == SIZE_CHOICES[0]:
+    WIDTH, HEIGHT = 144, 154
+    SIZE_PATH = "images/assets/0"
+    if FONT == FONTS[0]:
+        FONT_SIZE = 11
+    elif FONT == FONTS[1]:
+        FONT_SIZE = 12
+    elif FONT == FONTS[2]:
+        FONT_SIZE = 11
+    non_movable_area = pygame.Rect(8, 19, 128, 128)
+    timer_area = pygame.Rect(22, 1, 55, 12)
+    puzzle_size = (128, 128)
+    win_area = pygame.Rect(55, 70, 55, 12)
+    
+else: 
+    WIDTH, HEIGHT = 202, 216
+    SIZE_PATH = "images/assets/1"
+    if FONT == FONTS[0]:
+        FONT_SIZE = 15
+    elif FONT == FONTS[1]:
+        FONT_SIZE = 17
+    elif FONT == FONTS[2]:
+        FONT_SIZE = 16
+    puzzle_size = (180, 180)
+    win_area = pygame.Rect(71, 98, 55, 12)
+    non_movable_area = pygame.Rect(11, 26, 180, 180)
+    timer_area = pygame.Rect(27, 2, 86, 16)
+        
+puzzle_version = settings_data["version"]        
+        
+# Seting screen and other stuff
+programIcon = pygame.image.load('icon.png')
+pygame.display.set_icon(programIcon)
+pygame.display.set_caption('Picture Puzzle')
+screen_info = pygame.display.Info()
+window_coords = [(screen_info.current_w - WIDTH) // 2, (screen_info.current_h - HEIGHT) // 2]
+screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.NOFRAME)
+clock = pygame.time.Clock()
+hwnd = pygame.display.get_wm_info()["window"]
+
+# Sprites generation
+class SpriteSheet:
+    def __init__(self, sheet_path):
+        self.sheet = pygame.image.load(sheet_path).convert_alpha()
+
+    def get_sprite(self, position, width, height, color_key=None):
+        image = pygame.Surface((width, height), pygame.SRCALPHA).convert_alpha()
+        image.blit(self.sheet, (0, 0), (position[0], position[1], width, height))
+
+        if color_key:
+            for x in range(width):
+                for y in range(height):
+                    if image.get_at((x, y))[:3] == color_key:
+                        image.set_at((x, y), (0, 0, 0, 0))
+
+        return image
+    
+sprite_sheet = SpriteSheet(SIZE_PATH + STYLE_PATH + "sprites.png")
+    
+class Image:
+    def __init__(self, sprite_position, window_position, size):
+        self.sprite_sheet = sprite_sheet
+        self.sprite_position = sprite_position
+        self.window_position = window_position
+        self.size = size
+        self.update_image()
+
+    def update_image(self):
+        self.img = self.sprite_sheet.get_sprite(self.sprite_position, *self.size)
+        self.rect = self.img.get_rect(topleft=self.window_position)
+
+    def draw(self, screen):
+        screen.blit(self.img, self.rect)
+
+class Button:
+    def __init__(self, sprite_position, window_position, size):
+        self.sprite_sheet = sprite_sheet
+        self.sprite_position = sprite_position
+        self.window_position = window_position
+        self.size = size
+        self.hovered = False
+        self.disabled = False
+        self.update_images()
+
+    def update_images(self):
+        self.img = self.sprite_sheet.get_sprite(self.sprite_position, *self.size)
+        hover_position = (
+            self.sprite_position[0],
+            self.sprite_position[1] + 3 + self.size[1]
+        )
+        self.hover_image = self.sprite_sheet.get_sprite(hover_position, *self.size)
+
+        self.rect = self.img.get_rect(topleft=self.window_position)
+        self.mask = pygame.mask.from_surface(self.img)
+
+    def is_hovered(self, mouse_pos):
+        return self.rect.collidepoint(mouse_pos) and self.mask.get_at(
+            (mouse_pos[0] - self.rect.x, mouse_pos[1] - self.rect.y)
+        )      
+    
+    def disable(self):
+        self.disabled = True
+        
+    def enable(self):
+        self.disabled = False
+    
+    def update(self, mouse_pos):
+        self.hovered = self.is_hovered(mouse_pos)
+
+    def draw(self, screen):
+        if not self.disabled:
+            screen.blit(self.hover_image if self.hovered else self.img, self.rect)
+        else:
+            screen.blit(self.img, self.rect)
+
+# Ability to move window
+def move_win(coordinates):
+    hwnd = pygame.display.get_wm_info()["window"]
+    w, h = pygame.display.get_surface().get_size()
+    win32gui.MoveWindow(hwnd, coordinates[0], coordinates[1], w, h, True)
+    set_shadow_style(hwnd)
+
+# Generating shadow
+def set_shadow_style(hwnd):
+    try:
+        DWMWA_NCRENDERING_POLICY = 2
+        DWMNCRP_ENABLED = 2
+
+        ctypes.windll.dwmapi.DwmSetWindowAttribute(
+            hwnd,
+            DWMWA_NCRENDERING_POLICY,
+            ctypes.byref(ctypes.c_uint(DWMNCRP_ENABLED)),
+            ctypes.sizeof(ctypes.c_uint),
+        )
+        MARGINS = (ctypes.c_int * 4)(-1, -1, -1, -1)
+        ctypes.windll.dwmapi.DwmExtendFrameIntoClientArea(hwnd, ctypes.byref(MARGINS))
+
+    except Exception as e:
+        print(e)
+        
+# Text render
+def render_text(text, position, screen, color=text_color):
+    font = pygame.font.SysFont(FONT, FONT_SIZE)
+    text_render = font.render(text, True, color)
+    screen.blit(text_render, position)   
+
+# MENU MODE
+def browse():
+    root = Tk()
+    root.withdraw()
+    file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.gif")])
+    root.destroy()
+    return file_path
+
+quick_game_activated = False
+selected_file = None
+
+def quick_game():
+    global selected_file, puzzle_image, puzzle_pieces, shuffled_pieces, empty_position, quick_game_activated, original_image
+    quick_game_activated = True
+    try:
+        selected_file = browse()
+        if selected_file is not None:
+            puzzle_image = pygame.image.load(selected_file)
+            original_image = pygame.transform.scale(puzzle_image, puzzle_size)
+            puzzle_pieces = cut_image(original_image)
+            shuffled_pieces = shuffle_pieces(puzzle_pieces)
+            empty_position = (len(puzzle_matrix) - 1, len(puzzle_matrix[0]) - 1)
+            quick_game_activated = False
+    except FileNotFoundError:
+        print("No file selected")
+
+def render_albums():
+    global current_mode, album_name
+    current_hovered_index = -1
+    if settings_data["size"] == SIZE_CHOICES[0]:
+        y = 25
+        size = [20, 25, 100, 15]
+        cons = [15, 195, 12, 3, 9]
+    else:
+        y = 35
+        size = [30, 35, 110, 25]
+        cons = [25, 247, 18, 3, 13]
+        
+    for hover_index, album in enumerate(storage["albums"]):
+        album_rect = pygame.Rect(size[0], y, size[2], size[3])
+        album_hover = album_rect.collidepoint(pygame.mouse.get_pos())
+
+        if album_hover:
+            current_hovered_index = hover_index
+
+        render_text(album, (size[1], y), screen)
+        y += cons[0]
+
+        if album_hover and event.type == pygame.MOUSEBUTTONDOWN:
+            album_name = album
+            if album_name != album:
+                album_name = None
+            
+            if album_name is not None:
+                current_mode = "select"
+            
+            return album
+    
+    if current_hovered_index == -1:
+        current_hovered_index = 0
+    arrow_image = Image((cons[1], 0), (cons[2], size[1] + cons[0] * current_hovered_index + cons[3]), (cons[4], cons[4]))
+    arrow_image.draw(screen)
+        
+def album_deletion():
+    # Not finished yet
+    pass
+
+def album_creation():
+    # Not finished yet
+    pass
+            
+# SELECT MODE
+class ImageRender:
+    def __init__(self, album_name, initial_index=0):
+        self.album_name = album_name
+        self.index = initial_index
+        self.image_load()
+        
+    def image_load(self):
+        global current_img, current_album
+        if settings_data["size"] == SIZE_CHOICES[0]:
+            self.scaled_size = (18, 21, 108, 108)
+        else:
+            self.scaled_size = (22, 26, 158, 158)
+            
+        image_list = storage["albums"][self.album_name]
+        image_names = list(image_list.keys())
+        
+        if not image_names:
+            return
+        
+        self.current = image_names[self.index]
+        selected_image = pygame.image.load(MAIN_PATH + IMAGES_PATH + self.album_name + "/" + self.current)
+        self.scaled_image = pygame.transform.scale(selected_image, (self.scaled_size[2], self.scaled_size[3]))
+        current_img = self.current
+        current_album = self.album_name
+
+    def render(self, screen):
+        screen.blit(self.scaled_image, (self.scaled_size[0], self.scaled_size[1]))
+        pygame.display.flip()
+        
+    def update_index(self, increment):
+        self.index += increment
+        num_images = len(storage["albums"][self.album_name])
+        if self.index >= num_images:
+            self.index = 0
+        elif self.index < 0:
+            self.index = num_images - 1 
+        self.image_load()
+        
+    @staticmethod
+    def image_save(selected_album, current_img):
+        if settings_data["size"] == SIZE_CHOICES[0]:
+            scaled_size = (18, 21, 108, 108)
+        else:
+            scaled_size = (22, 26, 158, 158)
+
+        for album in storage["albums"].values():
+            for image in album.values():
+                image[0] = 0
+        chosen = storage["albums"][selected_album][current_img]
+        chosen[0] = 1
+        with open(DATA_FILE, 'w') as data_file:
+            data_file.write(json.dumps(storage, indent=3))
+        image_rect = pygame.Rect(scaled_size)
+        hover = image_rect.collidepoint(pygame.mouse.get_pos())
+        if hover and pygame.mouse.get_pressed()[0]:
+            puzzle_data[f'current {puzzle_version}']["selected_image"] = IMAGES_PATH + selected_album + "/" + current_img
+            with open(PUZZLE_FILE, 'w') as puzzle_file:
+                puzzle_file.write(json.dumps(puzzle_data))
+                load_puzzle()
+        return image_rect
+    
+    def image_deletion(self):
+        # Not finished yet
+        pass
+
+    def image_creation(self):
+        # Not finished yet
+        pass
+        
+def reload_chosen():
+    for album in storage["albums"].values():
+        for image in album.values():
+            image[0] = 0
+    with open(DATA_FILE, 'w') as data_file:
+        data_file.write(json.dumps(storage, indent=3))
+
+# GAME MODE
+def timer(elapsed_time):
+    hours = elapsed_time // 3600
+    minutes = (elapsed_time % 3600) // 60
+    seconds = elapsed_time % 60
+    timer_text = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
+    return timer_text
+
+# Puzzle loading and running logic
+def cut_image(image):
+    piece_width = puzzle_size[0] // len(puzzle_matrix[0])
+    piece_height = puzzle_size[1] // len(puzzle_matrix)
+    pieces = []
+    for row in range(len(puzzle_matrix)):
+        for col in range(len(puzzle_matrix[0])):
+            left, top = col * piece_width, row * piece_height
+            piece_rect = pygame.Rect(left, top, piece_width, piece_height)
+            piece_image = image.subsurface(piece_rect)
+
+            piece_layer = pygame.Surface((piece_width, piece_height), pygame.SRCALPHA)
+            
+            if puzzle_version == VERSION_CHOICES[0]:
+                layer_path = pygame.image.load("images/assets/piece32.png").convert_alpha()
+            else:
+                layer_path = pygame.image.load("images/assets/piece45.png" if settings_data["size"] == SIZE_CHOICES[0] else "images/assets/piece60.png").convert_alpha()
+            layer_path = pygame.transform.scale(layer_path, (piece_width, piece_height))
+            layer_path.set_colorkey((0, 0, 0))
+
+            piece_layer.blit(piece_image, (0, 0))
+            piece_layer.blit(layer_path, (0, 0))
+
+            pieces.append((piece_layer, (left, top)))
+
+    return pieces
+
+def load_puzzle():
+    global puzzle_matrix, original_matrix, empty_position, puzzle_pieces, shuffled_pieces, puzzle_size, directions, cell_size, number_of_rows, original_image
+
+    puzzle_version = settings_data["version"]
+    image_path = puzzle_data[f'current {puzzle_version}']['selected_image']
+    puzzle_image = pygame.image.load(MAIN_PATH + image_path)
+
+    directions = {"up": [4, 8, 12],
+                  "down": [],
+                  "left": [13, 14, 15],
+                  "right": []}
+
+    puzzle_matrix = np.array(puzzle_data[f'current {puzzle_version}']['matrix'])
+    original_matrix = np.array(puzzle_data[f'puzzle {puzzle_version}'])
+    empty_position = np.nonzero(puzzle_matrix == 0)
+    number_of_rows = int(puzzle_version[0])
+    cell_size = puzzle_size[0] // number_of_rows
+    original_image = pygame.transform.scale(puzzle_image, puzzle_size)
+
+    puzzle_pieces = cut_image(original_image)
+    if np.max(puzzle_matrix) == 0:
+        shuffled_pieces = shuffle_pieces(puzzle_pieces)
+    empty_position = (len(puzzle_matrix) - 1, len(puzzle_matrix[0]) - 1)
+
+load_puzzle()
+
+def shuffle_pieces(puzzle_pieces):
+    global puzzle_matrix
+    numbers = list(range(len(puzzle_pieces)))
+    np.random.shuffle(numbers)
+    puzzle_matrix = np.array(numbers).reshape(puzzle_matrix.shape)
+    save_puzzle_state()
+    update_directions()
+
+    for i, (_, (left, top)) in enumerate(puzzle_pieces):
+        row, col = divmod(numbers[i], len(puzzle_matrix[0]))
+        puzzle_pieces[i] = (puzzle_pieces[i][0], (col * cell_size, row * cell_size))
+
+    return puzzle_pieces
+
+def move_pieces(clicked_row, clicked_col):
+    global puzzle_matrix
+
+    zero_positions = np.nonzero(puzzle_matrix == 0)
+    zero_row, zero_col = zero_positions[0][0], zero_positions[1][0]
+
+    if clicked_row == zero_row:
+        if clicked_col < zero_col:
+            direction = "right"
+        else:
+            direction = "left"
+    elif clicked_col == zero_col:
+        if clicked_row < zero_row:
+            direction = "down"
+        else:
+            direction = "up"
+    else:
+        return
+
+    if direction in ["up", "down"]:
+        pieces_to_move = puzzle_matrix[min(clicked_row, zero_row):max(clicked_row, zero_row) + 1, clicked_col]
+    else:
+        pieces_to_move = puzzle_matrix[clicked_row, min(clicked_col, zero_col):max(clicked_col, zero_col) + 1]
+        
+    if direction == "right":
+        puzzle_matrix[clicked_row, clicked_col:zero_col + 1] = np.roll(puzzle_matrix[clicked_row, clicked_col:zero_col + 1], 1)
+    elif direction == "left":
+        puzzle_matrix[clicked_row, zero_col:clicked_col + 1] = np.roll(puzzle_matrix[clicked_row, zero_col:clicked_col + 1], -1)
+    elif direction == "down":
+        puzzle_matrix[min(clicked_row, zero_row):max(clicked_row, zero_row) + 1, clicked_col] = np.roll(pieces_to_move, 1)
+    elif direction == "up":
+        puzzle_matrix[min(clicked_row, zero_row):max(clicked_row, zero_row) + 1, clicked_col] = np.roll(pieces_to_move, -1)[:pieces_to_move.shape[0]]
+
+    save_puzzle_state()
+    update_directions()
+
+def update_directions():
+    global directions, puzzle_matrix
+    zero_positions = np.nonzero(puzzle_matrix == 0)
+    zero_row, zero_col = zero_positions[0][0], zero_positions[1][0]
+
+    directions = {
+        "up": puzzle_matrix[zero_row + 1:, zero_col].flatten().tolist() if zero_row < number_of_rows - 1 else [],
+        "down": puzzle_matrix[:zero_row, zero_col].flatten().tolist() if zero_row > 0 else [],
+        "left": puzzle_matrix[zero_row, zero_col + 1:].flatten().tolist() if zero_col < number_of_rows - 1 else [],
+        "right": puzzle_matrix[zero_row, :zero_col].flatten().tolist() if zero_col > 0 else [],
+    }
+    
+update_directions()
+
+def save_puzzle_state():
+    puzzle_matrix_list = puzzle_matrix.tolist()
+    puzzle_data[f'current {puzzle_version}']['matrix'] = puzzle_matrix_list
+    with open(PUZZLE_FILE, 'w') as puzzle_file:
+        json.dump(puzzle_data, puzzle_file)
+    
+def update_puzzle_data(completed, sorted, current_time, current_moves):
+    print("saving2")
+    path_components = puzzle_data[f'current {puzzle_version}']['selected_image'].split('/')[2:]
+    current_data = storage[path_components[0]]
+    for component in path_components[1:]:
+        if component in current_data:
+            current_data = current_data[component]
+        else:
+            print("Something went wrong while updating puzzle data")
+            return
+    
+    print("current_data:", current_data)
+    initial_chosen, initial_completed, initial_sorted, initial_moves, initial_time, _, initial_current_moves = current_data
+    initial_completed = int(completed)
+    initial_sorted = int(sorted)
+    initial_moves += current_moves
+    
+    initial_time_seconds = sum(int(x) * 60**i for i, x in enumerate(reversed(initial_time.split(":"))))
+    current_time_seconds = sum(int(x) * 60**i for i, x in enumerate(reversed(current_time.split(":"))))
+    total_time_seconds = initial_time_seconds + current_time_seconds
+    hours, remainder = divmod(total_time_seconds, 3600)
+    minutes, seconds = divmod(remainder, 60)
+    formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
+    
+    current_data = [initial_chosen, initial_completed, initial_sorted, initial_moves, formatted_time, current_time, initial_current_moves]
+    print(current_data)
+    storage[path_components[0]][path_components[1]][path_components[2]] = current_data
+    with open(DATA_FILE, 'w') as data_file:
+        data_file.write(json.dumps(storage, indent=3))
+
+def fade_in_out(rect, duration):
+    fade_surface = pygame.Surface((rect.width, rect.height))
+    fade_surface.fill((0, 0, 0))
+    fade_surface.set_alpha(0) 
+
+# SETTINGS MODE
+def play_music():
+    music_file = settings_data["selected_music"]
+    volume = settings_data["music_volume"]
+    pygame.mixer.music.load("misc/" + music_file + ".mp3")
+    pygame.mixer.music.set_volume(volume)
+    pygame.mixer.music.play(-1)
+    
+if settings_data["music"] == MUSIC_ON[0]:
+    play_music()
+
+def play_sound():
+    sound_file = settings_data["selected_sound"]
+    volume = settings_data["sound_volume"]
+    sound = pygame.mixer.Sound("misc/" + sound_file + ".ogg")
+    sound.set_volume(volume)
+    pygame.mixer.Sound.play(sound)
+    
+def set_hue():
+    if settings_data["gui_style"] == STYLE_CHOICES[0]:
+        hue = 204
+    elif settings_data["gui_style"] == STYLE_CHOICES[2]:
+        hue = 255 # ???
+        
+    keys = pygame.key.get_pressed()
+    if keys[pygame.K_LEFT]:
+        hue = (hue - 1) % 360
+    if keys[pygame.K_RIGHT]:
+        hue = (hue + 1) % 360
+        
+def export():
+    # Export data function, not finished yet
+    pass
+
+def reset():
+    # Reset all data function, not finished yet
+    pass
+
+def info():
+    # Not finished yet
+    pass
+
+# Stats
+def stats():
+    # Not finished yet
+    pass
+
+# Buttons
+if settings_data["size"] == SIZE_CHOICES[0]:
+    px12 = (12, 12)
+    px14 = (14, 14)
+    timer_button = Button((0, 0), (7, 3), px12)
+    menu_button = Button((15, 0), (80, 3), px12)
+    hint_button = Button((30, 0), (95, 3), px12)
+    shuffle_button = Button((45, 0), (110, 3), px12)
+    close_button = Button((60, 0), (125, 3), px12)
+    finished_button = Button((75, 0), (7, 3), px12)
+    not_finished_button = Button((90, 0), (7, 3), px12)
+    delete_button = Button((105, 0), (95, 3), px12)
+    continue_button = Button((120, 0), (110, 3), px12)
+    settings_button = Button((135, 0), (7, 3), px12)
+    quick_add_button = Button((34, 30), (22, 3), (55, 12))
+    new_button = Button((150, 0), (80, 3), px12)
+    info_button = Button((165, 0), (7, 3), px12)
+    stats_button = Button((180, 0), (95, 3), px12)
+    to_left_button = Button((0, 30), (44, 136), px14)
+    to_right_button = Button((17, 30), (86, 136), px14)
+    BACKGROUND_IMAGE = Image((0, 64), (0, 0), (WIDTH, HEIGHT))
+    ver1_layer = sprite_sheet.get_sprite((147, 64), WIDTH, HEIGHT, color_key=(255, 0, 128))
+    ver2_layer = sprite_sheet.get_sprite((294, 64), WIDTH, HEIGHT, color_key=(255, 0, 128))
+else:
+    px16 = (16, 16)
+    px20 = (20, 20)
+    timer_button = Button((0, 0), (8, 4), px16)
+    menu_button = Button((19, 0), (118, 4), px16)
+    hint_button = Button((38, 0), (138, 4), px16)
+    shuffle_button = Button((57, 0), (158, 4), px16)
+    close_button = Button((76, 0), (178, 4), px16)
+    finished_button = Button((95, 0), (8, 4), px16)
+    not_finished_button = Button((114, 0), (8, 4), px16)
+    delete_button = Button((133, 0), (138, 4), px16)
+    continue_button = Button((152, 0), (158, 4), px16)
+    settings_button = Button((171, 0), (8, 4), px16)
+    quick_add_button = Button((46, 38), (28, 4), (86, 16))
+    new_button = Button((190, 0), (118, 4), px16)
+    info_button = Button((209, 0), (8, 4), px16)
+    stats_button = Button((228, 0), (138, 4), px16)
+    to_left_button = Button((0, 38), (66, 191), px20)
+    to_right_button = Button((23, 38), (116, 191), px20)
+    BACKGROUND_IMAGE = Image((0, 84), (0, 0), (WIDTH, HEIGHT))
+    ver1_layer = sprite_sheet.get_sprite((205, 84), WIDTH, HEIGHT, color_key=(255, 0, 128))
+    ver2_layer = sprite_sheet.get_sprite((410, 84), WIDTH, HEIGHT, color_key=(255, 0, 128))
+
+path_components = puzzle_data[f'current {puzzle_version}']['selected_image'].split('/')[2:]
+current_data = storage[path_components[0]]
+for component in path_components[1:]:
+    current_data = current_data[component]
+    
+completed = current_data[1]
+not_shuffled = current_data[2]
+timer_text = current_data[5]
+current_moves = current_data[6]
+
+if completed:
+    state_button = finished_button
+else:
+    state_button = not_finished_button
+
+game_buttons = [timer_button, menu_button, hint_button, shuffle_button, close_button]
+menu_buttons = [settings_button, quick_add_button, new_button, delete_button, continue_button, close_button]
+select_buttons = [state_button, menu_button, delete_button, continue_button, close_button, to_left_button, to_right_button]
+settings_buttons = [info_button, menu_button, stats_button, continue_button, close_button]
+
+do_not_save = False
+
+def button_check(pressed_button, run, current_mode, timer_running):
+    global completed, not_shuffled, timer_text, current_moves
+    not_shuffled = current_data[2]
+    timer_text = current_data[5]
+    current_moves = current_data[6]
+    do_not_save = False
+    if pressed_button == close_button:
+        run = False
+        save_puzzle_state()
+        update_puzzle_data(completed, not_shuffled, timer_text, current_moves)
+        reload_chosen()
+    elif pressed_button == settings_button:
+        current_mode = "settings"
+    elif pressed_button == menu_button:
+        current_mode = "menu"
+        timer_running = False
+    elif pressed_button == continue_button:
+        current_mode = "game"
+    elif pressed_button == delete_button:
+        if current_mode == "menu":
+            album_deletion()
+        else:
+            # Not finished yet
+            pass
+    elif pressed_button == new_button:
+        album_creation()
+    elif pressed_button == quick_add_button:
+        quick_game()
+        current_mode = "game"
+        not_shuffled = 1
+        timer_text = "00:00:00"
+        current_moves = 0
+        do_not_save = True
+    elif pressed_button in [not_finished_button, finished_button]:
+        # Not finished yet
+        pass
+    elif pressed_button == info_button:
+        info()
+    elif pressed_button == stats_button:
+        stats()
+
+    return run, current_mode, timer_running, not_shuffled, timer_text, current_moves, do_not_save
+
+win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE,
+                       win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
+
+win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*(255, 0, 128)), 0, win32con.LWA_COLORKEY)
+set_shadow_style(hwnd)
+
+def data_check(current_mode):   
+    if current_mode == "select":
+        background_image = ver2_layer
+        current_buttons = select_buttons
+
+    elif current_mode == "game":
+        current_buttons = game_buttons
+        background_image = ver1_layer
+
+    elif current_mode == "menu":
+        current_buttons = menu_buttons
+        background_image = ver1_layer
+
+    elif current_mode == "settings":
+        current_buttons = settings_buttons
+        background_image = ver1_layer
+
+    return background_image, current_buttons
+
+# Game state
+run = True
+current_mode = "menu"
+# Dragging and mouse interaction
+dragging = False
+can_move = False
+start_pos = (0, 0)
+pressed_button = None
+clicked_piece = None
+# Select mode
+clicked_image = False
+image_display = None
+# Puzzle-related stuff
+last_shuffle_time = 0
+# Timer-related stuff
+timer_running = False
+timer_start_time = 0
+elapsed_time = 0
+total_paused_time = 0
+timer_button.disable()
+
+while run:
+    background_image, current_buttons = data_check(current_mode)
+    current_time = pygame.time.get_ticks()
+    
+    screen.fill((255,0,128))
+    screen.blit(BACKGROUND_IMAGE.img, (0, 0))
+    screen.blit(background_image, (0, 0))
+    
+    mouse_pos = pygame.mouse.get_pos()
+
+    for button in current_buttons:
+        button.update(mouse_pos)
+
+    for button in current_buttons:
+        button.draw(screen)
+
+    clock.tick(FPS)
+    
+    if current_mode == "menu":
+        selected_album = render_albums()
+    
+    if current_mode == "select":
+        if image_display is None or current_album != selected_album:
+            selected_image = ImageRender(selected_album)
+            image_display = True
+
+        selected_image.render(screen)
+        
+    for event in pygame.event.get():
+        if event.type == pygame.QUIT:
+            if current_mode == "game":
+                save_puzzle_state()
+            update_puzzle_data(completed, not_shuffled, timer_text, current_moves)
+            reload_chosen()
+            run = False
+        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
+            if current_mode == "game":
+                save_puzzle_state()
+            update_puzzle_data(completed, not_shuffled, timer_text, current_moves)
+            reload_chosen()
+            run = False
+        elif event.type == pygame.MOUSEBUTTONDOWN:
+            if not non_movable_area.collidepoint(pygame.mouse.get_pos()):
+                can_move = True
+            if current_mode == "select" and event.button == 1:
+                clicked_image_rect = ImageRender.image_save(selected_album, current_img)
+                clicked_image = clicked_image_rect.collidepoint(event.pos)
+                if clicked_image:
+                    current_mode = "game"
+                    shuffle_pieces(puzzle_pieces)
+                last_click_time = pygame.time.get_ticks()
+                
+                if to_left_button.is_hovered(event.pos):
+                    selected_image.update_index(-1)
+                    last_image_switch_time = current_time
+
+                if to_right_button.is_hovered(event.pos):
+                    selected_image.update_index(1)
+                    last_image_switch_time = current_time
+            
+            elif current_mode == "game":
+                if non_movable_area.collidepoint(event.pos) and not timer_running:
+                    timer_running = True
+                    timer_button.enable()
+                    timer_start_time = pygame.time.get_ticks()
+                elif timer_button.rect.collidepoint(event.pos) and timer_running:
+                    timer_running = False
+                    timer_button.disable()
+                    total_paused_time += pygame.time.get_ticks() - timer_start_time
+                        
+            if event.button == 1:
+                dragging = True
+                start_pos = pygame.mouse.get_pos()
+                for button in current_buttons:
+                    if button.rect.collidepoint(start_pos):
+                        pressed_button = button
+                        run, current_mode, timer_running, not_shuffled, timer_text, current_moves, do_not_save = button_check(pressed_button, run, current_mode, timer_running)
+                    if settings_data["sound"] == SOUND_ON[0] and current_mode == "game" and non_movable_area.collidepoint(event.pos):
+                        play_sound()
+
+        elif event.type == pygame.MOUSEMOTION and can_move:
+            new_pos = pygame.mouse.get_pos()
+            offset_x = new_pos[0] - start_pos[0]
+            offset_y = new_pos[1] - start_pos[1]
+            window_coords[0] += offset_x
+            window_coords[1] += offset_y
+            move_win(window_coords)
+            
+        elif event.type == pygame.MOUSEBUTTONUP:
+            dragging = False
+            pressed_button = None
+            can_move = False
+
+    if current_mode == "game":
+        if timer_running:
+            current_time = pygame.time.get_ticks() - timer_start_time
+            elapsed_time = (current_time + total_paused_time) // 1000
+            timer_text = timer(elapsed_time)
+        render_text(timer_text, (timer_area.x, timer_area.y), screen, timer_color)
+
+        # Puzzle
+        if pressed_button == shuffle_button and current_time - last_shuffle_time > 500:
+            if not_shuffled:
+                np.copyto(puzzle_matrix, original_matrix)
+                save_puzzle_state()
+                update_directions()
+            else:
+                shuffle_pieces(puzzle_pieces)
+            not_shuffled = 0
+            last_shuffle_time = current_time
+            
+        for row in range(len(puzzle_matrix)):
+            for col in range(len(puzzle_matrix[0])):
+                if puzzle_matrix[row][col] != 0:
+
+                    piece_x = col * puzzle_size[0] // len(puzzle_matrix[0]) + non_movable_area.x
+                    piece_y = row * puzzle_size[1] // len(puzzle_matrix) + non_movable_area.y
+                    screen.blit(puzzle_pieces[puzzle_matrix[row][col] - 1][0], (piece_x, piece_y))
+
+            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
+                mouse_x, mouse_y = pygame.mouse.get_pos()
+
+                clicked_row, clicked_col = (mouse_y - non_movable_area.y) // cell_size, (mouse_x - non_movable_area.x) // cell_size
+
+                if 0 <= clicked_row < len(puzzle_matrix) and 0 <= clicked_col < len(puzzle_matrix[0]):
+                    if puzzle_matrix[clicked_row, clicked_col] != 0:
+                        move_pieces(clicked_row, clicked_col)
+
+        if pressed_button == hint_button:
+            screen.blit(original_image, non_movable_area)
+        if number_of_rows == 4 and puzzle_data[f'current {puzzle_version}']['matrix'] == puzzle_data[f'puzzle {puzzle_version}']:
+            render_text("You win !!", (win_area.x, win_area.y), screen, timer_color)
+            completed = 1
+            not_shuffled = 1
+            
+    pygame.display.flip()
+
+pygame.quit()
\ No newline at end of file
diff --git a/main_data.json b/main_data.json
new file mode 100644
index 0000000..ccfdcdd
--- /dev/null
+++ b/main_data.json
@@ -0,0 +1,107 @@
+{
+   "albums": {
+      "Original images": {
+         "1.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "2.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "3.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "4.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "5.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "6.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "7.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "8.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "9.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ],
+         "10.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:34",
+            "00:00:04",
+            0
+         ]
+      },
+      "Birds": {
+         "1.png": [
+            0,
+            0,
+            0,
+            0,
+            "00:00:00",
+            "00:00:00",
+            0
+         ]
+      }
+   }
+}
\ No newline at end of file
diff --git a/main_puzzle.json b/main_puzzle.json
new file mode 100644
index 0000000..eea5db6
--- /dev/null
+++ b/main_puzzle.json
@@ -0,0 +1 @@
+{"puzzle 4x4": [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 0]], "puzzle 3x3": [[1, 2, 3], [4, 5, 6], [7, 8, 0]], "current 4x4": {"matrix": [[6, 8, 0, 12], [1, 11, 13, 15], [5, 7, 14, 4], [2, 9, 10, 3]], "selected_image": "/images/albums/Original images/10.png"}, "current 3x3": {"matrix": [[3, 6, 7], [5, 4, 1], [0, 8, 2]], "selected_image": "/images/albums/Birds/1.png"}}
\ No newline at end of file