From e22fcadb229ef240613c9a7a14d382805420c02f Mon Sep 17 00:00:00 2001 From: funman300 Date: Wed, 29 Apr 2026 01:20:31 +0000 Subject: [PATCH] feat(engine,assetgen): generate 52 individual card face PNGs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the single shared face.png placeholder with 52 individual card face images (120×168 px each), generated by the updated gen_art tool: - solitaire_assetgen: add ab_glyph dep; rewrite gen_art to render each card with FiraMono rank characters, programmatic suit symbols (heart, spade, diamond, club drawn via circles/triangles), and standard pip layout for numbered cards (A–10) plus large face letter for J/Q/K. - CardImageSet: replace single `face` handle with `faces: [[Handle; 13]; 4]` indexed by [suit][rank]. - card_sprite(): select the per-card face image by suit/rank indices. - spawn/update_card_entity: suppress Text2d overlay when PNG faces are loaded (rank/suit baked into image); keep overlay in solid-colour fallback for tests. - gen_sfx.rs: rename `gen` variable to `make` (reserved keyword in 2024). Co-Authored-By: Claude Sonnet 4.6 --- Cargo.lock | 1 + assets/cards/faces/10_c.png | Bin 0 -> 6232 bytes assets/cards/faces/10_d.png | Bin 0 -> 6370 bytes assets/cards/faces/10_h.png | Bin 0 -> 6097 bytes assets/cards/faces/10_s.png | Bin 0 -> 6151 bytes assets/cards/faces/2_c.png | Bin 0 -> 4593 bytes assets/cards/faces/2_d.png | Bin 0 -> 4597 bytes assets/cards/faces/2_h.png | Bin 0 -> 4506 bytes assets/cards/faces/2_s.png | Bin 0 -> 4603 bytes assets/cards/faces/3_c.png | Bin 0 -> 4815 bytes assets/cards/faces/3_d.png | Bin 0 -> 4851 bytes assets/cards/faces/3_h.png | Bin 0 -> 4697 bytes assets/cards/faces/3_s.png | Bin 0 -> 4812 bytes assets/cards/faces/4_c.png | Bin 0 -> 4884 bytes assets/cards/faces/4_d.png | Bin 0 -> 4988 bytes assets/cards/faces/4_h.png | Bin 0 -> 4756 bytes assets/cards/faces/4_s.png | Bin 0 -> 4869 bytes assets/cards/faces/5_c.png | Bin 0 -> 5099 bytes assets/cards/faces/5_d.png | Bin 0 -> 5201 bytes assets/cards/faces/5_h.png | Bin 0 -> 4950 bytes assets/cards/faces/5_s.png | Bin 0 -> 5089 bytes assets/cards/faces/6_c.png | Bin 0 -> 5368 bytes assets/cards/faces/6_d.png | Bin 0 -> 5475 bytes assets/cards/faces/6_h.png | Bin 0 -> 5201 bytes assets/cards/faces/6_s.png | Bin 0 -> 5362 bytes assets/cards/faces/7_c.png | Bin 0 -> 5163 bytes assets/cards/faces/7_d.png | Bin 0 -> 5231 bytes assets/cards/faces/7_h.png | Bin 0 -> 5017 bytes assets/cards/faces/7_s.png | Bin 0 -> 5153 bytes assets/cards/faces/8_c.png | Bin 0 -> 5600 bytes assets/cards/faces/8_d.png | Bin 0 -> 5700 bytes assets/cards/faces/8_h.png | Bin 0 -> 5444 bytes assets/cards/faces/8_s.png | Bin 0 -> 5573 bytes assets/cards/faces/9_c.png | Bin 0 -> 5677 bytes assets/cards/faces/9_d.png | Bin 0 -> 5738 bytes assets/cards/faces/9_h.png | Bin 0 -> 5489 bytes assets/cards/faces/9_s.png | Bin 0 -> 5678 bytes assets/cards/faces/a_c.png | Bin 0 -> 4735 bytes assets/cards/faces/a_d.png | Bin 0 -> 4734 bytes assets/cards/faces/a_h.png | Bin 0 -> 4628 bytes assets/cards/faces/a_s.png | Bin 0 -> 4714 bytes assets/cards/faces/face.png | Bin 213 -> 0 bytes assets/cards/faces/j_c.png | Bin 0 -> 5094 bytes assets/cards/faces/j_d.png | Bin 0 -> 5104 bytes assets/cards/faces/j_h.png | Bin 0 -> 5009 bytes assets/cards/faces/j_s.png | Bin 0 -> 5085 bytes assets/cards/faces/k_c.png | Bin 0 -> 6158 bytes assets/cards/faces/k_d.png | Bin 0 -> 6084 bytes assets/cards/faces/k_h.png | Bin 0 -> 5989 bytes assets/cards/faces/k_s.png | Bin 0 -> 6148 bytes assets/cards/faces/q_c.png | Bin 0 -> 6388 bytes assets/cards/faces/q_d.png | Bin 0 -> 6301 bytes assets/cards/faces/q_h.png | Bin 0 -> 6206 bytes assets/cards/faces/q_s.png | Bin 0 -> 6379 bytes solitaire_assetgen/Cargo.toml | 3 +- solitaire_assetgen/src/bin/gen_art.rs | 539 +++++++++++++++++++------- solitaire_assetgen/src/bin/gen_sfx.rs | 4 +- solitaire_engine/src/card_plugin.rs | 162 ++++++-- 58 files changed, 524 insertions(+), 185 deletions(-) create mode 100644 assets/cards/faces/10_c.png create mode 100644 assets/cards/faces/10_d.png create mode 100644 assets/cards/faces/10_h.png create mode 100644 assets/cards/faces/10_s.png create mode 100644 assets/cards/faces/2_c.png create mode 100644 assets/cards/faces/2_d.png create mode 100644 assets/cards/faces/2_h.png create mode 100644 assets/cards/faces/2_s.png create mode 100644 assets/cards/faces/3_c.png create mode 100644 assets/cards/faces/3_d.png create mode 100644 assets/cards/faces/3_h.png create mode 100644 assets/cards/faces/3_s.png create mode 100644 assets/cards/faces/4_c.png create mode 100644 assets/cards/faces/4_d.png create mode 100644 assets/cards/faces/4_h.png create mode 100644 assets/cards/faces/4_s.png create mode 100644 assets/cards/faces/5_c.png create mode 100644 assets/cards/faces/5_d.png create mode 100644 assets/cards/faces/5_h.png create mode 100644 assets/cards/faces/5_s.png create mode 100644 assets/cards/faces/6_c.png create mode 100644 assets/cards/faces/6_d.png create mode 100644 assets/cards/faces/6_h.png create mode 100644 assets/cards/faces/6_s.png create mode 100644 assets/cards/faces/7_c.png create mode 100644 assets/cards/faces/7_d.png create mode 100644 assets/cards/faces/7_h.png create mode 100644 assets/cards/faces/7_s.png create mode 100644 assets/cards/faces/8_c.png create mode 100644 assets/cards/faces/8_d.png create mode 100644 assets/cards/faces/8_h.png create mode 100644 assets/cards/faces/8_s.png create mode 100644 assets/cards/faces/9_c.png create mode 100644 assets/cards/faces/9_d.png create mode 100644 assets/cards/faces/9_h.png create mode 100644 assets/cards/faces/9_s.png create mode 100644 assets/cards/faces/a_c.png create mode 100644 assets/cards/faces/a_d.png create mode 100644 assets/cards/faces/a_h.png create mode 100644 assets/cards/faces/a_s.png delete mode 100644 assets/cards/faces/face.png create mode 100644 assets/cards/faces/j_c.png create mode 100644 assets/cards/faces/j_d.png create mode 100644 assets/cards/faces/j_h.png create mode 100644 assets/cards/faces/j_s.png create mode 100644 assets/cards/faces/k_c.png create mode 100644 assets/cards/faces/k_d.png create mode 100644 assets/cards/faces/k_h.png create mode 100644 assets/cards/faces/k_s.png create mode 100644 assets/cards/faces/q_c.png create mode 100644 assets/cards/faces/q_d.png create mode 100644 assets/cards/faces/q_h.png create mode 100644 assets/cards/faces/q_s.png diff --git a/Cargo.lock b/Cargo.lock index f2c784f..98491b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7514,6 +7514,7 @@ dependencies = [ name = "solitaire_assetgen" version = "0.1.0" dependencies = [ + "ab_glyph", "png 0.17.16", ] diff --git a/assets/cards/faces/10_c.png b/assets/cards/faces/10_c.png new file mode 100644 index 0000000000000000000000000000000000000000..1c68e0f641866d063d691269555712c3f7ea65d6 GIT binary patch literal 6232 zcmd^E3s6&68jjM6h%TAT2R0+8Nhv9;>ZjkZyv015W;+lh4rZSBXw^gcocl^ilk$~Lzu3-?D*Nf< zLT3ec>RQ(HK#=W#sH=>QQV(gR(>d%aQ(`;)ba~~J(N-aJF5!Ha1@r9p2=b#r{aCW` zT2@-mJEH>_rH$?i;CHtaNtY^UhhmE+bNd)!@ODou4Y5{+nf7q4JITi=wI-rt?`w!T z0=eaPNt3EG$MB92j!Q&uR}k_#KkH7bSfl1P#?HZB%+2 zQUs-|%GJfC0uYx5Y08)O`I`<4Z6CB}8$YBT38~Nh_cN6UliTXT%ynT@s5Se+h2-M6 znEoG=gE%!k(Pf3QntUoka#Pu@%f?3|5OaR?{mnIX%SSr>c}GxZ75C$+?SK8v-K;{T zI4(^!wt(y)Tmh3><(ek;ScEuN)77CHl8F^o$71zBwfZR6@n>$2MmnUdwCYNIhL@Lh zGeWX_SY>_Fo%s%l`9fA(V$R3016N~D^PPXgd(E-NR(lQZe4jD}(WkURWa^|`YQo6W z^!^8%q`isKGfq{@Le**mF6hK*QdHHCH7awoK~ugE+KYv6*ZNCpt4%j*x)!SES#{aP znEfnIe=yeM$2)=2cEO{Id{@%^!Zl631^F?9p;-(C_ zNv(fPAU-tsFoSFpxMp$Ckp(C|JRGVX9#9|Kwp`)-yW-_qF4cva<_kxTOHpfj^eg<+_hI{bm>l(Q%=}9eAUcoUJhYidvle^Qp(HCkJhiVo0B%>XsUCUT!&+;_%iFDzr2{=7?b*MTS@QBXWpXd22HJ*G2Q(<_5dBdGe{P zr6F~J>2C94$lMOhYrbkmk!gu8+_Z}rU(e}FQuij!G)>`}Rzxd-Io4n|SuBbv=h`nqs^`&t+?O8{{1OC%~uxpvZ=H!i#o- zMb85ikcl2Z(H&61>8AjJRIu3kn%$rk5;AwlicGL4?tvL8f+|oe5Ub z@hr3rU>n{&?=W|_(TgB26KD}s<3txR;>}J{AY$C9BtQn~D-dbuDG1xd0 z#IlafT5yi{2|y=;q`EOhZ-iW=SA(d6+t{s7z+0d2)Rr#zVSRjlA}av@!y-^u>=9Id ztPg;itv|IAs_>-yMC8oGcBCi@ph5{~N-u>|x|B_+p2cIYho+@a_d|uTBwNgae1*q~ zSMLok6OTPz+{{(5EGl8SALe6GfLZrZKqmmmuPkE)MG2J;dx|+It4wa18Z8jW*pSIo zAlKB@r)VmBLDCR5>7bATP$>4Kv>92NyQ%S_Gp|CqZnKrW0XB_{*<@EnSZs`&L zR=Jkdw=#$UbeRV%SRbq%{T}+RgwHEQBw(7GzJ)LmQa$9OLt&X<8$x$aMbCS|A3sC& zS!p$AFp3Ij$6=L50rjMl)=pn-7JU?C$I2dR{5=!LA94n&(SKWcuX{-BZX15Zs$eyI z)OLW7p7boA0vT{u7b%5e`d?FC_r(No#g7fX92~iF6r3v{I|te3!$+IA3}ghy0sF94 z@J;&~(8ci0-eS0Y41w;z&(%};UJy|b%m}1+vsz#NjZUX;L`Y{=8fK2d@DyY`c%&{Y z_B5DRfT76@#n?7Qv)PBIM9*-wv9~pLD8qIdwZ9zqhqTJB{Z9rUH+~|o8&D6QH5Vvs z>CBX%CW>%%@M=-=HflbL+0D_8mLh!>1RXF!IEUL`l@2ya3z(Szu3w0aXqhp^)h831 zqo{3xL?g=K6(J;=;jk=gmPO$^Ld>J=9s*m@pnM)eHe$DZE@SnY^O$l4=SmQJNf$HRYO;?D z=@4+sFD$YhDKaqbD=Npn#tc5g%>K^-i)@W~w$ApM0AT}v=;@1#f{ z1=|vlu@p=CO6xz!dI7mwXge(I#a-?E*8H4r{72iN1A`ghkS$!-GBBy}uRSTZ%x&1y zU7tMI^5*99dM_drL-=9l-K6bpp8*zy#XMd{ z_7zb}@k;}dv5!y29%k;{$U!4h{hk26cutYj@>&*Q%?XN^Mc(#>_!q*>=eR)mCOf?y zXfS)Xt6AlvaN%rgz=~MlC@e@kk6_g-_F;Y%Xdo2|ns);<%w=Xg$AMfH_JeDHuUZ?x z(MqO*vo!?jJQ(xCz#L<5xCebe+8x|Hz}|B94gj1yG^xAlx1{>JUw*w7OmqqI i*y#oHd>%c$<<7kGbEYN+F#j>&Y}y#V;qtq`J@hX~6%o$> literal 0 HcmV?d00001 diff --git a/assets/cards/faces/10_d.png b/assets/cards/faces/10_d.png new file mode 100644 index 0000000000000000000000000000000000000000..59f253170ebb9d30873ee944a466a413bea60935 GIT binary patch literal 6370 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 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/10_h.png b/assets/cards/faces/10_h.png new file mode 100644 index 0000000000000000000000000000000000000000..568b8cde007e9cd08f4fa4f72ce574bd2997ec75 GIT binary patch literal 6097 zcmeHLeNdw$RJK1Y5Ryf=K6#Ss=aOA7kQ`3XiKumJ zUX%I^Rr#J;v@_@H5g-}<_-aF8(xx{`_O+MZ``UX{k+V^ycyal2!?yR!{*+vh5uVV> zCyZglo)SAYRbF3~npr*oUNDEb{x->)?k^2;{k^+gJ(R&|Dod>|ds^cgso8yg02~uJ zN<${BW3&)BnM{0W+Ig?}05!q(@rdIh?PQ!8IyL?S)mgA+T zfEm9dy6|Zb$U}M#Bwg&=tGBJWOWx4Gh+5a~jOg8ax3V$8*rX?C@A-9i5eOzM`;dw0 z>fRW24JX9lqrW7s(C4WShDSQ4?c^D?n{zFnT*(C2LyW6+X_^h?Lkp1u8L7GzNnPhU zk7gpKX*^Pn{3S+hsb5JZ>aT7C5fB`@QjmdOY8Ha9wzPgf!=V+aOA1nOV;5@5;58lZ zH0JM!7^$o52>{s+a_CH4j_piv^+MFL;rswrTPAP!_c7%uU&Gl-Aw zbbeK7C7jRtn>4%AUsKon7;H687nFU3%(JF_i*g#cc@aG@Lsz z98vGi3zZFBUTK-6x_nlW5~{Gog;AvfDyxzrvEJuN7yW`)!?jI}?8iHhdsV1No(ZyZBf#_$yArY>X&Pnx_Mr6Di+64D zt|+HNX^S28Tm8F)-EZN@!D1>NvLQt~^MYr%Db$?UQRK2GmWB@c1=cp{O%tvu0(0PE z)^Yg}9|pD7E6_;-5;u6VUbz634XmmB<-HfwLoeXk=m-zQS)9wy51<7Q?dwN!3xluR zJKo}X{7;Ln#}X7+L?gwiq^ZO(-sl1jjfqunbmc#>iUweeCUb&@<`O&)F#)EGYr!Dw z9j67{hM!HO-{nl8bz@Kt(a)miXpvFja?e%*Zo4IrOiKW9>tz>Br&D70>}pg6*?ZP+ zL^b+Pow6D&rL&;^?M}n&Nu5*T*5)9S&)ckkh&!IG)~eL7^4Z2plo*1a?PBt&qag#W zOz^ohss^MQQXg`i*1x}*ju%X%W8gJ0pKF2K0tC>x`52f-$GI{f&7P+|8NUF(V!|zB zXro;qks(EBgn$;B=n~2tV1V8Pi(wOsVDJ%Cfgqd3Bi04sjrFkfqk=4ka#y&}&GQoY z^$9FG(K=5s4QMM(5%(%XOAsv2Tt;%M-O2y&4Z_LyUXV*^HlXTN!f-u|l=T*xIqU|L z`%M;2SPO&`!7k&k*mYP4QHrt4IG$aH(NGIP%UJZ|?11uNE+58&o@bS&&>g(HW&_~b zYjM)P;wG7Iph59vybHMw;ea&Ldf_m7U~vTkVCigSojQKLfWd?5NY?Lrlgoi1;s2jW z_x%R^=uAFdJO(OmaQFTo3idAVcoZROwn5d`ut_5+9OAnuN>P=;G1|9ekWSF zhbK{BDGl{vySy_$Mr}4p6Cu-Z?N@GTXT7nmX35Jg z4&+*Du{yECb7*&6*2nH&!Uz#-&COI>uC`hTdOOC3h|7N)OW`U;W`*EdB?#oo2MJS$ z7Y}em+`o*;jSs%`<%%@XAtK+xgO;acze%jaRT!?uTTG3e4WD-U+L&dxQ*zv!vtjbjqTWW_IRP0EpufrEj(szasu7y5 zxVBe>wOm<{fZX+!c_rv6s-N%LaYXv3w;oq~PkE;l&DbfvEO9 z?Q`KO$H}{7pMDEpq4^ZE27KFH>z(lJ{N$-R)Ep{HY~CLWqCzf{1*V{tj(nnaU5B>v=4wORx literal 0 HcmV?d00001 diff --git a/assets/cards/faces/10_s.png b/assets/cards/faces/10_s.png new file mode 100644 index 0000000000000000000000000000000000000000..527fcb93aed21e7ed501ace7936c120ec1189c74 GIT binary patch literal 6151 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 aJbWebi?d}E2foT7R%K?b(7g5Gp1%Q@+z49$ literal 0 HcmV?d00001 diff --git a/assets/cards/faces/2_d.png b/assets/cards/faces/2_d.png new file mode 100644 index 0000000000000000000000000000000000000000..bc296d68c0b9294ac4f7b6b0c44085cc4168a314 GIT binary patch literal 4597 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 An*aa+ literal 0 HcmV?d00001 diff --git a/assets/cards/faces/2_s.png b/assets/cards/faces/2_s.png new file mode 100644 index 0000000000000000000000000000000000000000..bec0fb853132bcb318e52857032e4d834e06705e GIT binary patch literal 4603 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 W@?YDu0KTYVMXrrrQ}w}T`F{gS$%a1w literal 0 HcmV?d00001 diff --git a/assets/cards/faces/3_d.png b/assets/cards/faces/3_d.png new file mode 100644 index 0000000000000000000000000000000000000000..71bb2df358907b3e3502d5eb7e79c0200c78723e GIT binary patch literal 4851 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 X9bPKlBf(x7k&-rV-Bi0_*TJ6wTp>t8 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/3_s.png b/assets/cards/faces/3_s.png new file mode 100644 index 0000000000000000000000000000000000000000..473aa947142cebcbbcc9c532b2322296705f8061 GIT binary patch literal 4812 zcmd^D4NMbf7%re-L{^>C>ZW#^Gi0K6j%$+ENPrz1w#O)1+6%e$bgMDJ{9T-}k-W z^Spmg4}B07?lb-6=@bgZCt}0;&ES&_{=S>$3Eus-Ep<>RFMboTK4c5qt-s0R%o|&a zTMSsnz|qzl6={)4H7WA?vDeNcWySB;mc8x&`hevN{;qxJ^8-Kaj8+UTSA1M!6;ID@ z=fed8Ew*%MIe6x2&Y`kt;CYW+)SplJi4V8)=P5mcmD?M%*fEx^p6Cu%}h3d@pEZb|8zq6smQU}>0(Ln}w>P`_iOTbl~NO(A>L5qk; zXA2rJ8?qWQ#XwwY*4+aGN0n@DqS`lb z%=zMiRqR}8UnM3WU7z+zV}enNIQXzSnd4Ud4yT*OIW7CFB^FE1mh&AmDb`|^Wv&O@ ziza+RQksLkC!@;<(-FN=!!HxR;K08}4Unw!=52@N5JdDeTd3 z2EsGjxNvHXmG{V*F*7&lVMKIyY(k%jEg6BCB5jrEt147ub!G=$5}kFgT6o1zIG1kT zuWP1d-%3t*1%k)gp80$O@V`TNJxl1%vYuzP?z*T3lzCguLDm=!xbnBm>`tc26*8LP zqY85hY~dmcxhuB2>wQ+mS1>F^lAeunT*OY??|9a zB)E5BsiT)87muk=E(gBot{in^8OaTC@9hg-sp8RN$Vv3CaXabJr$>JI9SHC*iA_X? zK1Qb2YY4~GehC4q>ARYa}*ilzo2>ycaJy>Aj+?FC$!#l6l{|`5uDCD1ZLLhAxqeO|FB2`|j2(OLeJB0c0Up5~mR(BGs50F>?GxG$loqAl= z^+=m@(CU#+Jk#-73nHJg8sr59?-E1?(8w7;!!sb^_&8PNx$3q5q4dF|IP4UH6e*dM zKP*dQ3|sK2z@BItr{sM!9^q1AX4rzy3|J&-2*o1to{w!K%zk9EA7TEGFndq7d4jVi zFc;viN&3ekzd-phFtbN8+i{`1CJ9ap3osWeotC(-$aHK)oz%xbUt_rWTN5j_Hu> zWwWoU)t)1^%XIt7VAbN_E@&uJabXqQEbVc%KxgPnL@&ZXp3FgjWa?PF$naK~+_@lu ztc4Y5zoMCes%q2ZDSTr9&$v@4D`}i1k+}LY-L#3<3fY@`1didr%uD>N$Y5I?bV8)d z-0kABS#~8Aokus!qU$6!VYD=#^T11gpA?x@=t#pzmyP{vQsQNu{sq=K7OJjw4TGss zVapX>ixa--8@0eo8IBD3T8>jK^AH0KIfg6X63wu4(t+vx=W2deOI%}TVBNNA_6cTY zSaJItv86=Z+%C4a4~9ZRr3)a=5tmD)0|QHd=tK^P9ddEfyCudS7`DyAoBvk?e zISq6^GZ)unWjs=EuEYYK$eMJUvsMPD_dK2`gZPubd@E5wi|~ePG`ff*LR1NGO@=OU s5%14j``(Dfm}dz|&U7SRgWQ+xNIJNam$wxBN=1nXi&|gv-i`ym0bpj00RR91 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/4_c.png b/assets/cards/faces/4_c.png new file mode 100644 index 0000000000000000000000000000000000000000..d749ec418bb1e0f35bebcaf6d80f4f0c355dac50 GIT binary patch literal 4884 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 Dfyt6I literal 0 HcmV?d00001 diff --git a/assets/cards/faces/5_c.png b/assets/cards/faces/5_c.png new file mode 100644 index 0000000000000000000000000000000000000000..c5e0cd6f0a72727a74ac33a9dee4880d42322030 GIT binary patch literal 5099 zcmd^D3rtgI6fUCR1XnlbYbxEtS9E%#xH);)F*J_3z@{>$JZjt$x2dgy(28v@${dPr zamK-nN?n%CDY0alP&;eO5C%@ATNIh8atnyXN^NO@zVF@t|0UM+zl(7*y2S)&a_M=0 z=R4=zo$sbD9zN{(VH^%;c*Vcn6c2|_WT~#qB_N6=S0@bI5Ka|9;ZBC=?GpW@|k8YUk zyh^%DZDywT&IHdQTt!^T81THqptY26epgA)tHv6`7Z|fonVBy|-fG^UH;`x%*Ht8L zJI2IoEe82e4$=~~z!=`Ty^^-Nszu%xIsZhV`g(p#qOV@y8>P3@=XB3b=>3*^^BAMX zteE;^`Hm=!)hnNtnR#H}QZ+SCdN#v0MP!f2>f^VlWCm{7VUfE`G`l8JT65ZVO@4EY ze5+GNaXY8V+ao2G7J0tXLt$Y`gnUP=uEwjime@z~d%`vSYjtrMerwNqsy~_2m8tE_ zjJAdGY_k$n3ip12QARnF-52z}k5;a|V2W++zSz1WGO=s4(xb41W^h1tq};gJ{w&e+ zfl$*EA$N+IJ<3X7J3$ZTlCEU6nN(s~7T8-zzgW|H`;3~h`dgO?Jl`uC(wRJ&LFFI8 z@sx?&qr;^&k(wx?^nkGNIl{e{Xd>wLv<=Nn7S+F=Kez~Zt*z(qY+=?~-HqDqyAs-; zAuQs}<*F8-IfM0kdEUcZ&$M-pBwnu;M5Z-HX?F|UUsH`dy3JZTPg2~{$zGRCUEdaI zcY}PG>Uu#urzL00aE1S>qBdUJVaRP})?p4s-R(%`!{ZGg>E>Z z%4=4idkv`L1kB=NtK&ll#^Y1S%)MI{m$krrxmY4J>G{P>3Pz+%3Is3F2INvWO<=ivG_r>XD8=CCOWOdIz6bF|S0bb@ zN1h5XT#)x5m2ZHa3T{IK)U8maby+t7r7l$*3}g-LK3^s>a2kUpa|i~)ypL?Y0+U8o z!cHU0v7mI9piRmQZ7MopP$JlLE~`DXDSYC%pv{voDEfFHYk2xo@3C2iveq0Z1;zsu zO60bKAXCt1y#+bK_K+nbigxHQ5~fcF35A)2rTGbLKPDd*!HXb5cte*Lnt*&2;BO`! z%NLUlg~uSQlYd}UBb$RgCFsSFB0xwjhef5U+_-53Uc|n16}DEY=VGNDs(VTP-{YLzE3P~m9yGV6{>(Q}U zsBrD%T?9AX0sA!!la;i|vtQvJ((07)_kqLFX>8+?)0|r_&66byweBeuhET4DcNEL@ z$n3>d32-^F+@thl44B}`^MmVhkkzZ@{q|i<-%z2>|MbsFQ#RE%(dE-K(G?0d%Q9om9?+Z{Z#zSI zk0+>D3}l1b^(#&749x_-{}R7051X0b{=H2wcF{K%3v;^bW5R2yXtT&R%WBt3+o#Is zDtc3RXW6B)TRUa$>y%%XV`tH6L-xG04%ZrR#viTm`vCa+n1(;}8R{gcBgr6T0XCyxd3pe%4I`JSRb; z1Ueao?d1=U>WB6!0oWYnfv;%tnwfOp%a_$VKikwZ@?-E4kCU<}b)oXjRongoL literal 0 HcmV?d00001 diff --git a/assets/cards/faces/5_d.png b/assets/cards/faces/5_d.png new file mode 100644 index 0000000000000000000000000000000000000000..b0414ca0771f7dcadd146a2096a3e754c1e27676 GIT binary patch literal 5201 zcmdT|4NOy46fPoS5KYzrV6ifRE$`~@m zu?57R7Bv}2Cu}aGBFF=QAyzDt5oHxy{uL=L6#CzH_uhR~n%-(QBWz3fN#48noO8eP zednC}GCtn8*2im>7lXm@S@+@UPssl~^0#pEB=Ya#&lcGj4Br{+R)>c3+|*U>`SUjC z{5A*@2aeyoU2tIi&f+*lsr_fqH=>-6N<{AjzA<1rB;9-XhxDL*En&)`CCVMeX5334 zlO|`D^?^mhOUP%Fj44bWi+tXxs8pvjnxx4x=?s;7h-&NAK5&9-DfOH19^9J3G^QlB z7lEKkwL&NeGRxlxumN@iGR>d=lGg+GDKK<#B^MvbGaVo(U}=N~w?I zOiZcl-cnh|@YA|!ZX}c&1M#Y6rD0XZ_jOww* zaz5DVFHAXiPk6A{tVB-8i)UdyES}jST*w3&e%pF~jX5VF49H4YO3+O6#)_i3aM=> z!<@r4z2=@=z&fT))A)A*KLsi6>@@B;#}eD&OoW@Vy_U3)N)y z1P&0X?9RI-)(=AZ)A7Y8u2(-f;Bu3~a#`6~nq~9-N)hjwAI{i%sW0?_hJGK5q>Gr3k?(`0xhsKpv02>ftTNtqV(5<}JYlrn z8c1?kgmBrzM7d8(YSqbAMPM_cK2{eyY~|NjgG_`?inPfQkSgX<0a(}D9iWmi}zr5gnc?SKARVIcL~@!X|qF!_HZ%SV*0a!J`jQh901Wvd`udGhK1{zfX|yi4cTS zX{_is#cDZ?PXV)rA!w72atr3v+Ng9J#T^tkEZ6B>&Qj5Gey0o>_*7=FV|eh$+yTRt zUU4;8ibxVH9i=f*ZtK3}IrxBf(dEo&qZl%h)kP5o1i-N8Qt7pZA>28^QCe-Fg^IzLODClog}07^7i3e?CnOLvHdGmw zil`jRrr?i03D=feDST6DyLG5tn15Q3Al@M_{-`$nVet~$;dfw04+_~M2eQD>?aVlh zMq31dC7jTNtaP60=r9T^`$u)_yNvBO%CjA5-56YLq2AQccuAelp< zpzuei^*%^^S|pk1_DlyJVvVSGx?U8)B(YJBuwes;c>?vi7&X7oL26h7Y93Y*JIzZ_ z^CggibbkRC5H10lOEmM@2!#l?h3bE0Q0Q0->b-5WhJh=n^%tdWd?wsiPDNJ+!6ld^ zSjkU6W2zYClK3B}`~qdj-V%JNIzx{+U=PZXJ+LAgzZ7=^=lBO(9Sj8Lr)lOhzt#%e9>xWs%q28dbA5Ny8_(e^vfp^YXw z3~bmjG+vm0kpkk|=8%`LA?ML-tcHcZIjfAz{60S88F`~q+j=wy>SKi=akvld!s~1s&pj4b^Opkw zr?xRhZ#tW#G^omu`)s65^Q~+;CXnr1u3x~ds;M+=Ns4!2yxiJyJZqP3di064#4vNv zC1USdWq9Z>qT?*SHzQX#vW(YPUctVHb*xRW`3t;VgH})>vs?k?xLhx}?)CGjgvXKC zcXd1c>T0llOQC<5)|I2!Ah3#ar(H~VtoX4tIW4!7gn9n%*fYJzweA1VI)9(bo6%xFqT7w zPuEA6w4@!}fMc@Nl>>Ma(&?z0It8hHauSY?Yg zlw2`T0`2!#TguZ{e_EZYtQq@k|4v-;zEr#{bb;2gOZG+fiNdfQ9Wli4Qetbh6`z_X zm*wuO(@;SVm(ss^ne+WHHvN0AvT>-8(JIT8%Vw!qk*b7R4Yi+dtKm#~3%;7~XU-Sg zt)Rjhhm^u847dt2QpM{2x{}nHYxuT6# zc`xKQ_HSyu%;4ymx(gZg=1{z;oiME^s`_AkkSV8idG6$9qR+QhBdSJF)+N{vC8-8< zwxi+p#lrj}w}hG1RszWoOJj@fu`#PnxWtbt;%ru*Njg$Vnvi6~%F7bVWHH&ux$Y~m zTx*^4tKtpvbN;2lDA~>qD&J9IhKcprd~LhVBtF}}npa#&s;%zKCe9FLwjb-nuCdi?akGEC zk#|d$r}Sf%@hv6%*P6U@o9gx4Lm}~fe2$?l(h|a#dW#%!G)@ns=2*S+W^~4nMCtb3 z3)PYZ+}<{+{hi3cLOgi?x$_UwJ-(#0RS~^4#f}-@DAT;l5_5c)3rEX$Y66IoN;27o z!2Q7>&bhW_^Dg;~cq4w%9V(400O2o|66Ctm6Xzfdsl@0C#{EsSEPV7#jy@#bC~BTK z3v#a}iL<9u2TCI-pK7ZFRhy6;zPSfmdv4H@OsDOGq@7`tuk-6k>itZ?+e1_7L548E z9BvLdn=U)TrM?RUFyF#%k0?|X)NG_t)oN}`#JB7Yxme^C=TPX~`D~ak%F;wNygC*@ z?#`{AYXJy%Cyv@f>ApLG^xY~$Y5BZMW6O`aFF&!$HSq;CUW9tyc_0kM5D*R?Zk#Vx zf)Y@%P;Y6Vn)d!bybWETZe|@)7rVeIya(WYDg|i3z5}RKPYk#Z1+(rUC@~H-L~VeA zlVtEKBi%Jpc;O$V{A49asP-lb&0t!JIMN|&5B&%RP zieVQ(35e#YH87t|Fds?33!r+$W2igM27>wUln~HH2uOg~FuB+adSR6_pPvDs#P!Z+ z5f3C6!+b1RkSCa^LIF#35XIo{plij{1DdEs06U`rl!EuCdpG`%taH3dA9u$6xMl6i_=hj1-tYBReBFyfku0?r4SxWJKjX~42MwHx&drK3oR*2FyF%TYxfO4+L(II_;;%rO3L6?sL~JumYbeB_pmn22mb*@@^f1uk zA05cb2~)%`Jp0iuUFYG(z|)8MJ#|Qp=sj$vAz8S)9M=^N>m_F9u0&ghr4*T|&+^b@lyP(;m4H53v$C%2^r{_u|kn$`L@4K z(}!oKs!d9I#pIQm`mHhcZPnEA;=3M6GyWvVN*WcJOt*z+;sR%8gg7+(Q`q1!%v_wu zG4{RaF;I$HbiescdpkbA@b$w|efn=S&Bq5*M(iHwp6Exlr`T_V1AFPx(VfrA2QI5M z0mmL0aW`4|K-T=&P&_jDGFYnNBpAh58nUUS?*yRZNDUwW%ahpQ=?cFBc8-3C%Z~#9 zwEl)APXrJOX9_$fU|SHE1D6qxrak+zhwgpuCwcm+C>Guaw8Tl>iKV# zU9wVwJD*){tI1vSo@|S@;qK2z2dm0nt*u%X`OF>1cKOFUPVSA#?nu!MEz!Lza}ps% zt#Z);ML)G@cnSC}$X?74hJ){KX;r4Z*pG5it9*_=Fi!vWxqj+%zN>*bWhE_I%&->= zZl0lHR3@!>8b)ggh|>pl@0NPZ_6ELd9`;WZDsJR=#*)oE@-dC6Ib(1sd-yn`?+m3t ztQbclIkr%x*(F|>mR9k_dW9}Z)Wo$s#~%txAK`S$i?ob@YQCe4zqBz})Og;~CGN`- z?;I=AF?tt>4Z%WFr#N5c)FELCb2zq0qS2)??;V=Ou?8wfvx#V~+icyU8(oFnPE+-! zg;@famKWJ_-0>ApU!)sbno;3|5A+_E+TWc$DQh!n(rp7*e)&Q0cnSEu5*vz-v`A#OFAzN!b{}9H z9$}dT1?BQipqcCUxja`j!?|#?EuJ~70+Ffop{j#C$CtXxOwUd8{wQHdXRrUdq!A;9 zqCvGdM1Es?4Az-ZI30KYf?tSH-O}cEP@55lLUT2-W6Qz<h z5jR*X^84ev%w97nYX7y`PB>U5MWKar^>iv@iXNoX!f6@*_bQTiPCGa??1bo|WS9&&`?PTJ2)O z7hoevq&6e|y`&r&!o)RbQwJNtg7?Cn;^%wFNV^&7NKz03ZD!Lp>nlM{J!k3sR-&28 zp>2Lc+iVyQkhq4XzZu$BK&8;mB1!7@NyxHh&}|y zL=Qw+EsZk5@VAc*;}|9MsPz3E-@~=OKX(qvLoi12@nyKQ(&D=oz(h+Q=b)z&V|Qu!M2T#mpi@v397owWB}Suft)cP-an=@+)KJS< z)|rQTFGcX-&@Z$Dzvih1TjOxReaG|)1Wlsi5F`S?g|W)NAN}S zYb_xxbqY1iuy!H049I<22{Pit`l|54IyGjI63z%^>v<&$x0f>87Zm-Zw)mCWQ7$Op z0VXWLxrJxBnRQ2PK(c~8T6f5x77x0X7Yt4H>rn&Kd7Nnk-mvEEd5QK6M4a|*eSN#l zhSuppXORF&^tBf5xf2KvgUk^u)qt&_g@x;oi!5M<@Y3tOiTDLy6`U2eJSd*&r*z(X z@*22|H5xyVe3D+m9qua>?1&aU49G)Ov? literal 0 HcmV?d00001 diff --git a/assets/cards/faces/6_c.png b/assets/cards/faces/6_c.png new file mode 100644 index 0000000000000000000000000000000000000000..0e3c3f5228f579b903bf5cd483665c4485bfb7ef GIT binary patch literal 5368 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 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/6_h.png b/assets/cards/faces/6_h.png new file mode 100644 index 0000000000000000000000000000000000000000..f2da2abb5ba5c46c3b63f6e32d9f40afb6060885 GIT binary patch literal 5201 zcmeHL4N#MH7$2fie%v%F0t>7x`;rBw)(O03njsxzCS-h;XPg;MUAckqzNB^JsbSnX zDr2*=oZtmVl!Iezn#xCr)EO=s_-^2wPRHIc_PxFT-v57Gt-b5I>pC;*j;|Z<|9PI@ z^Zb6#^ZegkFQl)SJ|$)fhr^kk`rNV?ncpJj`^YVmnV*lo@`#Vax&5xxWlz5(3NsxK zKR9QtxZMJTBYQi~$hM}ft1r?V8~@s{Ms6^l3aWssxu$k*!K zswrjN^3vTcM)1hkJm#~>&T_6Oiurt4qcl};zL%GF%kR>Lr)YDVjo<^m=UCi?CFp25 z*I6#q)q%xIlLo(qgRF$5Xu~hOca%0ekMTYCa{h|JNo$i$nRZ;is8e6nlZ8(@mT%kN zY$OO~FYNZ6d5x z^@IZ@qZ2zWIH$jyZ0Wk@Yv+3|@mx7I#lSIC2U=JOHQ3c$JmI_Z4_4B9rLtCg42Ra; zk+=Kh$3$n$bYhmT*H%Q@pW$52W+IzLg~d_vNpeD@S1+HLWakn!o@Cn~DQ(LKMR}Jb zvdw)UCj^e4J@`Y_xL#e{HP^Rby&$}Nu0ofs>-(g`JHiu$JfZ=En6`^=txvJi<}Ws4 zqdWVVPcBBs(OZ=C>XdXf;a#yc)Jdy=l$R|M;`XSazLt2A&5U@zFrk)lqNPs zkW0_J&Xkoo`1`UlXzpR5Sp$Tn8o6%<$1Uc&?hG$I9-)|;wB@CN9jVA1|=HgAcnV{ zj%IRsG8j5F03A5hqJC?ywhlzId1&BeB)=ck*DWC?GpwV6^Qo9k6dRvbJU;HAo8^G# zf)T!xXZOx$RCk!A>E)JcS?sBC^Y&o#H&(f>3!%Ij6wHWVJ1hxIzQO*LL3)DNuS&Ab zmS|w6V9Jx^kTi5_SupFtpueOg@I2@Bf zX0b(e4)Hk?;VDGa8V@L*r42%k@O*>t^x9EC=VAIl4U6XB*58Cia!1_WtB^8eB=f7Fi}{QXGAN-$9cla{y7-};c8b|_#A z!cMd7Vm%N$cMK_WVt@?Kv2zv)-G)(q5yMA0eycwOTfK>PkLxnb{&t1`KOKJ^*Ehj* zTo$0UE+|)ye>jfa=)?eGd+w|84SV86SF4Q3oz=?fc-CK zl#IrkyLE9Onr9nRt+Rcd-F4{xg?Zja#cbBVSpx*V!8Ao;V`G6`8`0>vs@h-vI=6UV ztfdKCNt}E;Ngm1p?G|_Jt5~7box@fYUN9%GP0{U2aur?JU!%sS$J)cm69P~0SYd85 zSIv3eJ8BEhQXi4-Nh6NW<#?1BP@+6z7ts^?z^!~|<{lw=GR-?E-K>%+uX?spGU7y9 zvYs#66bj6sbpd%QSL!*PWK`qgp6arPf7ZUx0uSF7T=7mii>n5Lc~!_sU7o(IerdsuUjQK)b;AGv literal 0 HcmV?d00001 diff --git a/assets/cards/faces/6_s.png b/assets/cards/faces/6_s.png new file mode 100644 index 0000000000000000000000000000000000000000..57067d38ba0ca546057b12317f2ea131dc78896d GIT binary patch literal 5362 zcmeHL4N#Nk9S=gqN|oN|m2S4ger#x|(9JrkAeoBC95-ld#Z3@)?rvO1Ax=&bAmn9G zv@HTxozQlYxLdDLIFs(UnleIOzyd0ibcfElKwhBvP;5v@4EcKVK6{=gR=GU6o3`Dp z*Xvyfx#W4C|JU#L`~RQ!jTdsVRxJO)avqPjV#m)jUxNR|@bA>JrSLsz&(i@O@1gD; znOj~KM_BtJPd@eQ)}eVInrk{gsyLASTV<*K?5)=;M`W$PP|1F>{)stnh5GkZ?;lPp zxtz;5)-n5(K6-i0h+5LvJqw<`xek7})KeQPj)&iWrq@~z^FCEeM%0f?MP^Lx{b&|6 z3;k#LOMZs8*2a2jMbjN1O>5Olm+|l^5gAjFhK5eg<~b|$KhFCy2i{lt@9{FzZmB8t zSIKP}M-sh6leuNx!ynN%z8Rd?HQrj&1G8ekCZ-!NR7Bm<$YH;+TZ^;<7q0oAga0I?kY&G z98axz(%@}pnmf5-e`rQz`g45lrGJ@?7vePYtLTVa$;>ft6XPkRF0@IM1`uExJ2{Jw z+*Z$L_q|$L>R3h3I}56<8+e+5B+bK(gLO<`vdG*4x`~2V7A~sTzh_2Kp2PH5zz~>Z z6m}S+nfnA`SOsutrac}b;FY+Fg-F%P!U3qzAZK~v)df$h8oISLEq`)P(qOQ@$ zMw}FSTZKRFi3xW zXn|ns@qVu3w&rziXdFBts#c3;vbDzY?pX?EAOv&`l{0bj(R#ilrt9hvm?R>%|3CQN zEguRWQsiu2R_nCL`@>ZL9Nno%_&6{or zYtaenA@sZihUDn<#u?UIy#F$IlvyYhMAbr)Xa{+GdxUMkSw4HIUi@Oa06d`d$)`hw zKrGE^uX-@0Bk25k3CYXTJ7Z_I9}IeTi15yfy<2lDxcN}hX;$A3?s*sn??liIQ>YuB zwiBCNtLH>PGfKkD-In5;4;C(Q(-(>05>fJSPPjxu95@B~HT_esQ#VD`p(013B611> z0>N|A1qdP_2PfPD;b0eBAc!p(MCEMQNO9k1MW`Y{V1c!S&Vc*x0E0S?F*b`1WvoQ) zY!wh z5^*9=VVk=aWlc>4MZJk^#vH(b96-d}f_EJwcn8K&APLuS9s5x#{)ktO6DxNI7=m^M zE^0V5BB&0J5$doDh`u{e69eMfVYYd}TA;)SKgN*&zUzf|T|aOP8I;K}CKU)D&T@ng zxsf26d&`=agR+D?M}9*WBlg3p@DSBe6XO)bSj;J~4y?vGPsa9*;br(c zDh6khuU&mWCQN&95(7`&`It%K<2h8HXbiO6{YZ#UqJo3x$d%}v*DbiA2BFI0`X`d` z4Avh{YG5VW6>rA%A0#j@z=|G(qzd-|JfLwsq~P2Gk^d(h^B#!2NId>a$Git3quDw* z9V2#4*ic4`u%!v41L#*j?)-`0B0>uE4KeZFQ5`FhPRC1+yQ)4((hQ6^dKv$^N7E{f zSO^t^w>bR`n#;FeQW!24OU;RY>+Kypqc#i;Q*4%lCHe!ph(rqPf0Y=sq;<42jeb$+ z$`cOJM9+a&5~ZlJ&257BJ)PJ$4w@C4t$EGO&EolZ>Y0@Dq0olXR**9PJ=N&YP+hdZ zvxW7kK;Dw7^V<^MlLxNyO@~$~KkFt?4&6C8vaV&?Za**QuFFrkt7*6K{#@}BLg!Cy z7fa}c5T| zk~F9FCvbB%?lph!jUH_Z2=0? zls2C<0eBJ}Xc@eZtEZ-8sWm!Xn6!WMhdVrnAen8P2_0<^%wVsL>O;+Tdzg7vfW<91 z10N-3m<~{h#sQrUZEqly8D4zx4FXS2=>kII;jJAt|H7A1>keCt;oBpGxa{lS-i54l zKg8D2)02=#b(9Q^A?0c4ew7^t&tKsQ-Iu#pzun2Hwtn%<@l7gfjll6*);r8e_$-sR NV|z}fa_evE{sV1t$zuQj literal 0 HcmV?d00001 diff --git a/assets/cards/faces/7_c.png b/assets/cards/faces/7_c.png new file mode 100644 index 0000000000000000000000000000000000000000..6714efb9301c2cb2af2a3301539aacc0bdb1b9df GIT binary patch literal 5163 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%0A?-|0uWzFKVtFZUV;OQ0s+5 zHXURNF~N~TMS_7oC_9b*VOxz{B)D=;;(Z7<#YI5`n8i$2i^tIJ-WF{#guv;iA~A<|J+ZH0_Ei z2NzOssYbS=)_|tmpN2mhX)6qqM&QqHx2b!JL|1BLmue>H0_W*II%z<=vYjWy!{(E% zg<-bB{LTs#tL|-+2aAZ6fO)#Wj;)ov(RL!+`I6}G7_4>QQ}VMPbZjiv=XEz`rrY;Q zHdXR^hp)l1wph;MG-YuEB^Pt9^{AS%4E3zbdD6gEQHPZD&txt6s=gj|E%P9Uc~3m> ziMSyJV+2SGbW5oANW*Kdb@tN#mS+{G%I(m zrl2h>;6S#$ID2|skgV>M$>q8d=AI?yJH_=lW`!xzXl@c-sH)#66S3H3la}ulPgiPc z4QvsW=n=JRIwwUZmFX(bT?{v8bws_l@_#~#GV9bN~e zWA}I;4^jm1f8jnTS0LnxkDj&OupsUVvA&Ns2@cO&a(LGan=u!PC~s1-Bhj~1jZiW` zgpY#SpjA)@_98L5nKrr^j1sh%BzFk#=3wBt@|{#cPnCkvpNP*^s6ARn93)Z@V{5=D z_Z#?R+5j(-9t=m5mg0iVn1=(gwGf{fu{eBJ7D+`crHp927x!oi1QpQ?4!AaoAq>#h zLqIs^gII_t6|BeA0IuP!oSc0W#Xd9{wrDiO^mSNipAFlSEUUExZ;S3O$2t&d3J{xK zO|!BTIk8;4NTnkMHiGpZ$co0I`bJ3vSW}6 zwww;ie<3R;GV7xRL?-olSX|+4yAhJZoT0$ukrt06wkmf zMuN5hpvcgI;=PaCsOtH@FcZv#VQo1{{#>ohXS3YpQhbf=!%N{Fceghw(IHT z0_|!Pxc5jQyVu*xwY|O**WnNq^p6jaEJz3KmE-~M+{aWpsR7Q<5 zaQ$G+EBSI zkFVNguCDTaoV=gyeMY{?{D#C5rFu=k;PHaSdRd6pd78PaMQ%y+%1FyA>E8)ily_&y zH$}&F#>=in7lb0ZfBqM=lnm$~L=hJRs+xv*5nKqJbjK}Uoxr#_3_9YulF-vt3bMc; zP^N_KqXnj7<`RsRl66=Hq;g7F@mDy|U_FDQAS!oxRjmEVZ_j|S)s+A;A_(}nhtgwH uP-CmVQ~Q&YmQ=T7EBWpLOHMcnZZ;kI(!{mz$6x)4;uj?@ta|I?&3^zPz+XoI literal 0 HcmV?d00001 diff --git a/assets/cards/faces/8_c.png b/assets/cards/faces/8_c.png new file mode 100644 index 0000000000000000000000000000000000000000..17e1de69d619c0d0ea98336397ff6bc853f4c528 GIT binary patch literal 5600 zcmd5=4^Wfm84sm`6>O}|VcS96R>oQXq#f-Phwak@lvm7TXY3=p6mPvLXCP>Jq za;>XY-04bA1wOCdH3C<--6oM56Bq+jlvvSnE|l;uMB~zYNeIc8Ki|9Wed7q@&CcDV zf9?n*`FP&v-|zW7&+~rp>)clsFM4VbkH=e_^J?~QxxaGmb#`G4_j`50vq2tjxjH9% z)9dmmTSxTiXSUY%IDqV{BbTnKOEq+VIoVAAQB_(Y(9&lY<$> zx5OsrTGP%JpMFtQpGI-G-3p$aTFZSGu}&Sq3D77SM1?;FpJ6WvzGhscGnN2Y#sH=IPtjeef zF5&rVrOfxE6&Y&axE8(={R@-aXJ4UTl(=3C zm?i9Di8Gn%tGqaPq4XBmZkpajJi3pQ)OGU&bd>#XWtAVOjya`2xh$ooERuh5rMv$+(Pk{Mbn}DLtE5Ie-HLkWDExYh=%_F zKwxuj{oW-8TYxFzY!qQO#+6xbR?C(5#a(m7wa=+@H~t}EA|$>B6L%r;-_#Qzp3BQ9 zo);)i9&uTyP7W=U(azHjqY86)WU=>R7F_;?i9E7qS zf{i9Ru|rK^uy_r7IM{jz(~$xnX6Xg!I(rT|e>;pJkc%OM)F7Q-K=%pczT_U%Z@N1d z%U=5|okba3C<4V0d29wA(=TV~{2eNRPmzOatPhX}png{wR{Grr%2SyXV`#;g4-OfY_1L;8Hr4f-`)fQ1T*br5T`;F zvL3Y;(1d02LFI1^qeX}_52~@iW`veO9Lp+b*ZnS#|J`~#2u%yIHRRU)$ORQ{V?sFh z;BBn19){H;;sv}8@gM3TGw-r7z2F7-(6R@THtLG<5;PR#;02WvW`BJjbTu>-h;gzO zLoSzZLXp@JmLd;fpb1q;Xikuz(ifshLrh~0;@d9$uVoOSMqpK-wh!aP-wpH7io%Bm zd6=Bo&}ihxMk6&EGf-awxhRbmL@3whGF(J}%sb*DA8444Cg?MYuJwx5;>v$~D)M$} zXx0u2wZN}WFc>13x}9*P>O1^8`$6BA!?r~C7t-J)+@gO#c&mv?xQ5=y(2X0NLl{Jx zS&Q#FKe$3US)|;r7MZ16*G#TatxjTT)x_H2vDcVMDf@1NF_KORy+G2FuQU((*DJ>@ z?i<43QW0}mZ02^=^56mqz126uS4twwdWI_nc1Mz+g9vnuS8&%ZsY>qZfzni*(u}wW zkXoUPWNCVOfzu%Xje*Yv!6#G1NfvIawg-M9b;kHUYxS4r)@|r7!*UKc<{iW4DyB~# zC{_Xw`B7?7uIrSZ$)wLCb}561f)eY^jDRYe$m(y!fV^K-KS`qiFFUztA;IE za2J0$33v(1$>M(cC5$7ui;Io_d{cP2D`|R((w$Gf@4q;;S^rd@`B+M(Ls(G~NdVp( zrBJ>`>bTHTDohkI$AtY7)@-7=i;)ewKp#PQ6b6~O9qTgi>LZq&dqN5`5OoR1qQ@klmGw# literal 0 HcmV?d00001 diff --git a/assets/cards/faces/8_d.png b/assets/cards/faces/8_d.png new file mode 100644 index 0000000000000000000000000000000000000000..dee330220fba84cda96743fe5268571f6479f002 GIT binary patch literal 5700 zcmcIo4Ny~877mMw6*ZlqQ`*{!-L*@ttJ!MZ6$K+JEM?i6T4d-}OLohk_@(f|nx1QE!8$nU%R?tNLv)Fu6xY+Hv zK@&~E)yw~I^12D+Odf0Rl!N60}JdJaD9jG&t%6?w46V#-MXgNy50-CAgS>v-`6c zYx9f3M)jHT@eg~zU$pj2?wmu4;T?)rR)jIg@KyGbNqLz>eoc6($hG!e`B2$KkA|pj z7~HVb6vk~DZ-V2+{6>JCXbQ+Y0BDCBzg96(fIJ@9Izvj&Phiw<^^Q`x%{cH&o?jxRwZX+mxQl zK7&c>y#7y->y5Or6-3f6Mt0h`-LgUrJE&UVJSlj+DWssO!MM5mA4#5xE&Me+#eL27 z!^#IWSG36k!-c(WoA%x-Vzc^AdK(qbSscC?)3JfS4u^@_w5M9HRMI#V za@lrM+VnHRp1=r1{juFDla=k5znC=gs@I+S^t8HY(Na$r|E-v;&ud7%E0AqzC!*iG zq?kCki>)~FnTpD#0&`~8i972C<84)vr7ayIVqU6OWy{psx3ETcQ0!l542m$WmcL4x z?;O6O^}V+SzV{@-_qqExLh^YkjVdgSUwMYlhnPI_ap!KTOro(e2{ps*LoJu|;^q`^ znWCQeX_o7x!1-)&K~so4l+(@^i?0ZF!3Lc&bqV9!ZQ>y|o^BL0HA!vkbCIO%lBLL_|4C+Is40dQX zTi9z+>4*xf+6a`(v=hj~2DGji62r)C#fZsmogo%kuOTI#X>xSR*5&6IzjGJINkvA4AUxvQTL3ZcTJ{-mEp7MjKf2Qg@JTpdF z9^yO=lTriYR83^4xQ9U^rs<$`rocfmge*&m;FCB5<&Kn~1S3OxkOK&=GnlJP6a?() z72qni0$hc`O-?~fK?aV~0fcK<}buC@E6B>ZFKbbk*_g7!?R3tQgvL zOq)Oisu6_x0SuQEkb?!A>eZUCJ$TbC#8<4yU>s%;#QCLhg&*&_v3)=o1ogjEbodDi z4&dXkJrOY_mKGDb_0Y6<2KV+EKUzqU@F<561E0bfh@zppkdZ&($CofXG*o3iu~B~K zr$Uj~JWEPY=(KBVQEg6*p zO8*-WJz9Lf!Ns=+hD~=0q*aKZVHiP~=(f{Fv;`WZMvIp)$C>#1!;A+{s55@u30%O1 zfNrF8cjDlc%t7+%YZmLUaKJi*=s8-ZhOnOcD49w{xuN?Zfv1G%_3INgIKv;Mu~Rb* zUpbCB2XxbugVY_^Sf1z@2+mJ876P?MgpYU>b3u$`+>IztH~%Smj=&|GHbl>aU>1Ar z|4V(ILJ(|2q49?y(&0U*qWbYXK8{jV`i)Rp+AghtD{#AekPqk};K@NfiB=cxjlg0x za=ZMfwhyw}*WM!Wnd5PW%CTvVNszoDu`b12eWHs4rrCzspm?H>?Rj;o@S5yW(Rcr{ zQfI`y1E6ueg*3EUuqH;Goz$&j=Ufq~h!{&Y*pF{8-4)zw6}zHt0bRK>R%=b!U^_18 z$Yv-W@x!}p?{llkPLA;%o^!_suSZs`Bu550H%eu>$?*Kz#k{JP<5)B4yeXafJ8@tC zrRg@OdF%#nI7{les(28(DM?*mbesDa(9^$QXe^f~+CskYl(c2vTc!QPtMwLcm3Qs< zuv<_3T!kG1;r&S7zlZ9|!S==EsOnr~dA3ze=+gz}dHG+f3!`i;St3m!OW-12Ue(m_ zC#M2mwdbG<=Yvj`gth&_`q?*0|uY7!E5-M`68& zWAiul{w#b?%Q2^ufhf_aGooXZd>Pg_sr`|T(Z@R`fW=7L=n0>ZzVrsagab=7mtljo zsJEh94r4Jk@lh8m)|qqb5rzzlA42J(dlQH0{SV{&zs>1Ca&XG-0V(K4s51qmn#y&T Y->U2vw$G(*hgpg7TjOef^T*=<02kNLrT_o{ literal 0 HcmV?d00001 diff --git a/assets/cards/faces/8_h.png b/assets/cards/faces/8_h.png new file mode 100644 index 0000000000000000000000000000000000000000..8beffa4e50b82805292cf50f47a64ccf5282569a GIT binary patch literal 5444 zcmds54^Wfm84tq>wc7N`IcBkDUCTUm$|iGlBOx&DQpO6kma;06cAn+bVhUU(kUt-l zT8bIelaq8x6VF~vg_d0PX3T(mFhyF>eQuzU227+t5D7^Lf&Bfxeee6RlFOUBRoAt> z-ti}w``+h$p5OC(e!utqs-MjgELrr(A{L9aB;)DL&(Z(I^zVnU3+caWwyh4bSW6$s z*qr{nILg)@ed381>n}N}(#e`nFKdc3cQzNA&dvSo{_v`kQpQ=jP zdo9~MwbuNnW*@#t)}xau^yAd(>9zEC3q2KVaXkI~7bb(Pigi^d?a}?n5}j(bn+KanyXTz9{}}6D0(y5>2_}L*(I@5I zz3=j-JC;k@j3*~1Ub{xUYMv?NFQ_n#Y&UeWIF2a$-%AoETNRqt3z9Q(U-BPYhZUa$ zOxTH*TfbT1jN`XYbm-_+dFZN^JDG+<62o*;aLgRsRoHrC=SE*um+MWVbf?h2g>y22 z@2b;}W6emh`a$1goC}@m;C=bN>sZu|iaFQx5KopdC=DDrlm68vJX*Fw0Z|Bw;vskha>^k3x4qDr zegtvrey0Xg6-fJ577upG7AOR~0}{jN@r}M7{MKlaH!lk}wiHK9&flUG@A4&xEL-qE z-GJSx^huVn>}2dFw^LXpfP$w>Z*zKgbN&HVM~f8@@1I zs>E+Moi}g2IU?)#yUjz1>M3L2&Mvy1Qz(2qXU)yGM&eYTZZZV#^ovg`Ee?V@q-mRt zIqUA$wm*)|2qFTZuPGp$(`--dgQO$-#D))#zGsv#SrND*e1=!l&_r5&;cUx4%-wdz zVB7x++i>t*g6^dON#<)O?za{&|1i#V|Cmfnl90>jhIJtg3j{_^$2d=x_qzy7Bee`= z&x}&D;v#;jM};lS4HAw*^UNmJ*mio*7CWLij&)oe++aigOdy%=&szwV`XJaq>pWvs zcjQpXG)sdIv3&I+?+>G;?J=zn5QI=w{!mh*l1D9W_Ni}$D~mXtoa(C-zdW}=J+gst z3S=1FHsLLxNBR%QNGpbtvUzXMg|~%=|7L{iTkAim@$_tE54{1<3;CplU4@uAzC_Q# z??C9m@0jln*%ZPR+=M)9wgI5Aj{(%=S*Go7&~{9NGz~X_xYRbl%Rqr24Cj~4Gwi^LMgIv=23B>^>l|6+JZj26+W9( z2Id6+943DR7P=C#Gg9N7$6Rdzpv1uW!j2(0U?;)&uwZHGVfxY73MMKdTVK2Dl3E`~ z6M$}oph8IF(bA0}Fi}U45~w3k0hspSL*WDF!9iL7p@kMjD+!`C*ZnnUM>E0vdyEi4 z>d@V9KMJ;wzXq#QBJxA!LZSv*0b#If2&u6_&}$atsc<%2{qo!xBB`_pJ&JHRhbl$3 z&JCKK_Z*OV0uUW$Jpcs~60--An4T#{mKj>1En!GGhe-}xz6DN<8PP|NJ#^suLwbRu z?*F}3fI2t^3{lLt0jaE3s8|^&XR85DEHUT_2FGJ=!pFj=KG7${O6fjnF^L6jb=Lg*o64i=w5Pl-dB+zXk^Ae|k0z(Q%o z|L45FWP_9Jf_5e<;=})wT|}bBT?Bm9Dz^yq_5{OGckjLrFvr?F7isVO%Pf|pQX`Js zNa@#+my;aRv%zQ8<+{?oYMs1f9oa_|kulh1w(peoU#Cl@+f~R365Pmj^0BVhoCWeX zl;z##hZVop=Q*EbV;NbkoyVsvB63gURi&~HWf74pZ{q|L_}Ut!{QeiR<*VP3j2PX| z2puo}ZM4#?w9bSp5`7^uitRG4o0nQK!sn{uMBY~>s7ZUtP~pu3$5W}~GC9Hn`bOFP zexgnm&=fla*zb5{4e#S*3P)1+UWY6i9wXT6ki^{uOT9X8r*T@~6#g0y1-aR9C zm5M)?U_W;WQX2%6k8nm>SFlIo4_tXX|5%*J`BUz&30L`fHd*SMgX-W@`9n@DtMtmU z6%kwoYsSlNWUiOo*d(6Tl8a~kex-avv3@vF?NM@dkyb#Ttk9>*{EZWAw&j;b@Rh1v_(*R(Dti0_UJ z-UZjc>fw!mei8&{EEc?4$$`dl`4KQG2{}RQBMdg-oVTWkH0^@c_6XeIY6Mi5Gu8;* zC+%JmfOlxc++`rbob-YO2pjOu_|b5a0PkhKyvB&PAbR+J0RO+9oO6T1gYa!2eMDbM b#ikG4SNC!C6#ZJ1#maapYjg8&Upnw_*4ZQv literal 0 HcmV?d00001 diff --git a/assets/cards/faces/8_s.png b/assets/cards/faces/8_s.png new file mode 100644 index 0000000000000000000000000000000000000000..74cfe046ad16dbc298a090cc347951e75db10168 GIT binary patch literal 5573 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 S>@_fF{o2AcjX!yP-@gI%gq}_S literal 0 HcmV?d00001 diff --git a/assets/cards/faces/9_d.png b/assets/cards/faces/9_d.png new file mode 100644 index 0000000000000000000000000000000000000000..939880df48eb91b80202389638a2e498b784fb96 GIT binary patch literal 5738 zcmdT|eNaDh1NKWAKg|*78ls z+Y@(-!$w=f&#&HFeQTT$jeXqSp*WiIPD7r)iT=s`sJ8ldjkUkn{PQu-G3CLcFDtel z>g4104fy^BuO_NQtCXBnS%`HL8_3TVxl7sN73Amrdi7`p>wBd{t9;%No?ytnY9T%m z`kG=FybiaPvfZVkzB*#7dQ>lsWI-!o35M{;@7D*d?k1t{71sY^&{K1abHo;bby(K& z-wA$Iad_n89QM1bG6FhR9`4%4`d6mfl=-YJEY`M>tL#jZe^-fnv)iw~>dnmG@BDMz z*W#~}9LMF}#Jk@uCigheJ#j6btzQ-0eIV|z66<=0(z3ix+<3`4@mM|9&)fAY$=%yW zI*BaYmB(9HN*<-Y$%?gwS=+)*2XErsfi=G#-y^(LuJP2XaGdM^+nM;0SGe8`>Dl_A z**i1nmtH$n?RRd=`Mgr-Sk85Sra9{iTwkx*SSW5!@%PFPGo4dV-1cJ2FNYNg=aK?; z{(W2=ZdOl5sQNc2$h)`2cAN~13y(7H%ZxYWa)&lN{>za1%9ndan;+F*AtJCFkJf7z zoN}LtHPjI*BvUH}47y<1<(7MY3NGMFwIbs!oo9DLz{WN*uKwdyM}FdC^Fv^LvL= zrg-Uwwia8&1YPrMLHonSv>Jgfm_vqX5Fc3^0x3W-xegkd(yegQ%!P93nHlwsa`^Gb0TRJDL|n*^v}tUk6i~s>9|x!hK-lE2nV8Xr%q{>LrkqXy zQHcLJzOOePw_cHr`Eyn7o_Q#0u62082TA z&~6!Ow+!ZRHw-Pq1H#k64IslUR)vS`wRIhHFL8?lY7R zAEI{8hQQQ2U3GrG9ic2Aa-M=oqX%*7M*pDWl@rN`;u0sO3!F#;kR8!L_!OR*QWsRf z1Vcl)&;bb71;o`Su2J(b=$2ciNUMMl!vIdq4+&^U)dIMMj{^G?mxVNdRgK#R=X$G{MuHpgI`Tl^6tqi~x@4VU`oSJ<}jLaIQkAkxqz^*ym-C*gZ|! zdsC$5qvgz>0}{{>-L&(8eY%0fp=C@pwIA1u<}z>0WsX@0A-D*&zY$LKCoND?^AY?h zk*0f9Bb?`Gh5HFwL&;F#sGee_ZVJ>awG_4cluAAZNc?|hBG@bF2^YO7@Taa)^w0{M z(ssnvCr&|TgSunZE-ZS5bVRW?-gK!W*1M#E`0J@Y^4h;ihg{Ua-Cu+aWfV-xBvp;R zAJ|>Dw9QM+YHLNeuM@YuDjlr&CSYl7EAY)63&~sAur$Kx zpL2U;AG4t(*biy&6XBlVHI$I9$V3C vavkyC@qN0TG$SB*AHHLfEqfUe8QH$Ga^)BLx5+nTR`QNFw>SLe_htVEG)LQS literal 0 HcmV?d00001 diff --git a/assets/cards/faces/9_h.png b/assets/cards/faces/9_h.png new file mode 100644 index 0000000000000000000000000000000000000000..5c7637168452ebdbb4c803b64fe8be32648be0c0 GIT binary patch literal 5489 zcmds54Ny~87Ji6hth5_v{K0NV*#0oIIyTeVu677XsdTN|U9($McB_(FMjh#5RJJC; zkVmmCw$@_nZ0Mp8>a@+)Oi5ct0t@7!5wyZK?kXZp;YAP-5Rw21`FVM7-@T7*-sWbe zu&&hYalbKkk=p6@%~cW&PL&HASxzG6}n%VDjr|?z^H$}IVb;< z;*?j~W#rfj^5v=kF|VN2tT|ja#4MXw!G1Q!S144)v!D0cEhEL)C9|g0yu=YJacr#} zV%}8*YZ7NY4PPx3`U;iTPcbQ$5xaIS2BXAC9I@SR7-^@kMiIOp`%eP;|GZzc*CoK) zh8~e+)1MdbxpgE<`0CQkkjk#H(UBP-|dP?bUi9Iw`b_TK1K$%Ua&qG*u48? z&+ExwsJ>V`en=lkyZH4_*mpeWJIRgyl+W`oURJd^nPpvr8CwD#vgcFhM7L$MSNg&# z&BgP3+nFt-H&;5lklo7Cj3v5aoM&VEa+*o;jilA?O^TL-gx^?4l49!P4^nU4FAijC z%Z&6uAo9=&50~gD&zh_g#}wm>#lGW2SukW>PCTksU3i}A((j43Pu_vE_ccB_Y>S2nggsGL@2DN$T`{rP`CQc| zu~&$f=Tl3f)>vvSSLR(`t1UWU@g6_a`A%^GW3Kkk6SZz+stfGq(0nYQQ}`FhYMKNM zakkuo;atkv+V~4y@A;l9^^FTUv_8QDs;cp_ftP6n+OztlS^k+6QD>VpkHhD$7Sxb(9LgSx-Qq$EO z>>dC+Za_dI>>w`lBH$&pGYE2&4{x_g4>Ic!0C6*<*lBnM8^_11fR9W$LRV%tt{zIG zUIA=y>G=tzAd;GgFr@1XVQ+6=f>qy~LLd;^nzA09LrF)7;M57%7p07VhN{=&%dY>1!#|-M50bt*Ju$4iO3Mq zkJO6j2mKP?4*RBmXeR7;d#1?ccR&Kf$T6Sit@?Gx3_q3#J^d`TZ$H8VYq+7PfR-xbzrF+ z{!#QR89K$YoOb^S@Fr^m%t?t1Qa_5GnThe>MZEK5LZO~Is2M?%)2S&mGr5Kz1BS-T zMr-~AuhN{cJPm6mLs=l3U_Ezs6QuYtK&TiOjGB%_-N+~r4rYc(gtybC#vKbt$=u;V zBm5+X7R}is&nTnl*9>s`Q4AL|F`k(;95>L(ArJA>(4^pWPsxzkoRW=)E6o{;Z~`*z z3501(I^ZwX0Olqs6iH5oWQg_MNv>6Q1wG{1Hxh%pHp$e>#)~Dd4@(ELSJVB9wsEA- z*!xaLmpst^Z750JH!Sg5PrDx%HP<B*O#ic?+~iz zmr$LFF)w}7c#f0|ZGXx;$7Hoy7`u8mQbG1|^Xqt}-(E~CG<1i`)t5RncTEO^rRrC& zC>yTnsl~P^mk+#(D41w{?7+1(sw*ODHFkM4DPi)IsU)W_iT0MLqV1B`X7-By}Iou%>}DUwS66rq@r8rayiUxk_V9bYGT!G}58k7ouOR0S zQ}W8JB#mJxL3^0|VZ$mjGj0)LK3T4gI(9t`n8SJRi?Pted@T_X5eqkAMvl zZbpt`>}~#CC@=7Cud0j!=JzGAlk-=2_m7&uAV^@q3p6P%YX5#W4>dd-g&+UL7lhND pT>t%+^nsB!J@c=xJm1D=|L&{UW0ts4@TDrY?%DO}RnNRs^iPRzF^d2I literal 0 HcmV?d00001 diff --git a/assets/cards/faces/9_s.png b/assets/cards/faces/9_s.png new file mode 100644 index 0000000000000000000000000000000000000000..de5bb85fd2657aa1b89656f642b4e65ad2bf565b GIT binary patch literal 5678 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 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/a_c.png b/assets/cards/faces/a_c.png new file mode 100644 index 0000000000000000000000000000000000000000..7d20378059a6b4605e2b0424da10d3a0ead58c4f GIT binary patch literal 4735 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 T`0JSel{oQB6PJ`O+O+o<08)Or literal 0 HcmV?d00001 diff --git a/assets/cards/faces/a_h.png b/assets/cards/faces/a_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ac010180765b83cfb1dfedad71afae6bce0d72d3 GIT binary patch literal 4628 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 diff --git a/assets/cards/faces/j_c.png b/assets/cards/faces/j_c.png new file mode 100644 index 0000000000000000000000000000000000000000..3d1642ce6adf25643780b5c2e18a29bb33466392 GIT binary patch literal 5094 zcmeHLeNdD49S@^Q&q8tMS$tVxwzb=dHEUUo0w#5}XO$i7s*H7DQtc||C`3TX3xr3c zid_rT?vxfJ;npc4C)u5Yhe$}`dn-ch3Fg`W4{tGTSl$hJe|~#@PkL<2@9Fj0bKM{7 z9gri*_xt;PKfllC`|`Z~o9wL#i&iXRu~-S)Uf%Kw^(v-*&py16`kVUuHDMNO$@y(t zHt!V2Saq>&PrZ8bx)X?O^&j7AFUxwptJv7{)z7|nK&B@thxUT_1;3?p+s>K_5QR`W36M|#;XSKWfQU7iCw)G&>#%< zr2Oaw+VoJO?~rKn9LUgEjnxmcXfH9`iP-TYouu8@BMh!$eHVv*mAJHt0Ab!#O^L?; zG(T`!aJZ8+2cjLy6};dD?L=1(UaZs(Vb8J+&JF0wj*y6mf-cwA>y~z3^pNcWw5tHIrmx;4O zm)Yjei;WstGKI}b@G(nfZDbO3L z2Afj(B%=t8}qmA2F98=1KR4JK~&&Pesg4hW#p4zy#*#!ylJpi#X57}1(& zD5$hv`QXgk*m-#IpaLm!;CTZ-_=_|9BFu4U#}MgbgWU%1yZf4bhIEWv9uj(^t58Vb zUM+Ct{^4o%%X?iX1b$D1WlV={ZO`6x%v?cn%SYIvndbvvKn09KhBM`o0tFy9Liu5R z2*1HcJKB@4mS=oTjMxE6`r;DEWne|53mR!@TPg7{K>$9Tmkfy`$|HH{^V0hNNm~1v z(P&b-boarN~psiA(_l8)ciw%y(UA)(vmPtCXA+P`y&|ZuR{gW2W zm&W5Cs;_3Lm)V`k_FJi1SE}Q79rvwkdmh#85{+H4hlcF#FLNZ6H^IY zNAmlZXJi;dg8OLA=*ICIzkEJho_Pr*A)w|05z-&?!h|#0O@Rly5nZtMkATO2aA?2$ zy7rfN;TS6^&o>R@)O}{)Xdvyn0sT?6LkW%A#Bf4A4ku8a;Jjv)Pn294Gp97n0z0=uz%W3|J`Q=wqf}ouXD$!llJ&M5I zNqT#y8!{vvP14+P&n}`y8NA3gs}TJ2!gePIbBol}D!Vboe>~+@q3mwEgUO*;dOfXV z`sm88_Stk6mz?I+!)4iAsrBYdAhwLz7bx#`Sog5u}xHrz_pfAzvew zqSr^$k%Fv1M9A2LSH`=#MDBR12gk+!CT#im^rrD6Ni*nGd>>CS{tNqs3JQbXs>Hh) z?yry@A$d?%Oi5#B;Bf0Mr^>8&Gm|-7?jnVh5#ygg5habl(V2-Adbk(+3>&D~IrBEd z6~#mINGXkFAk{aSf79vZ)amruILs0Txd0hE{uht5{^Ri)`D3qC_m;sF+DSdXV{LmW LdrQ}^UOW6xARc7> literal 0 HcmV?d00001 diff --git a/assets/cards/faces/j_d.png b/assets/cards/faces/j_d.png new file mode 100644 index 0000000000000000000000000000000000000000..814d75666d702a78b0453568c146d77cdcf57459 GIT binary patch literal 5104 zcmeHL4OCO-84hIyCrH@oQQBFFwnKJQhJRH%ls_XQ_8KI zH@=DmncIWwzVmw3)o~!SoVa#Vb}(g+e4oB)=I5bnqEDI1HTzBlOA=A*3J%3`hZ>4D(nft}4Ja8lrH z;ykf|ezlbCDisc11W9VMzGM!IUL`1bAh`c<18H?N3A{^K|IC8!(8lF?%J=e zI3X$drrc9I7PuFzB!YYxkNs((CXW4c(@x@0sQ8{F|1QWP9Q%0RC{>T_P+wtjY(dsf zHG9Q+v#&#|S|{tbFT!s3h}UNNb@qLPV-xHC4(cDnZ9yE{N?*#6B+IasZ^~F}ms{J* z)fR1w36~@J@?Yr7i^ah!iW~JpacK0^JN#Q2AYZIk`XgDMDuH`JaB+L6Dh#|gcrwZD zl@w;Awv8p(>J;9COli0z;ljS_gyyq`gMT9l`yY0Q`j)E}$cV9>EhEb{#~MhZC$Pw5 zOcd^j5_!DEa}rB#$qt&2;*m_ra+R%WoA!ac?MPQ9_WF?|>*&cea>eI-l^DV{IXIt%HTpQ>*zmZjGszQZXEX1?BSAhX1yf48QUDQvZp>19w3L z(wYn)EDkJOrk@xOTq?_scPhntc2J$bT_sr69$MVqN-enP>tFD=DL!reG0A!m&eT0D z-8WJnnx~n0{vZ&fE(v@--k0t0B{Z9GDFUX$ZtXVqkXzI{sT;TmM93gT4a4wJqd(E{ z${WZWcVNG>f2rZx7n3pZMdUMCb{h$%+XpTx!zTu&*GB=H{VH5v_0XL|^%I@l|9pV_ckU4MWceP{cCG>2V~No? z7hysAsu_(}h@XD>DX<;3)+cZV&ZLh&Dd|ZLKVN}=1i?Wny@B8)6>e=VC#3tb=5wtS z4*`0VBzyYoG5jY_t2UhOn|zxf3`Z}QxaM9 z<^RppyB!X9^-Z<|go;>gC+}3JW_01ErR*si z$D3S`?Oe?iny^R}$R4)jSsMz>UrpLqc+8L7v3us1x{JN^R@b zkK>mR9BMKms5;do?yaTsl%lXy)!pj!f+n}-KFUNF z&E~=S^fc)JIF79TFL$5+U+}9tcu)@68k!!LhCx{@kc_=Fo8r9)it&4pO`Wt7fJUU@ zpz#YzkclcvCanZz&{5d%JLu{(SA+Lx$x*G7kD;6Q>dE%@%V)F6)B$G1VL(e%tF zqfxY5v`%Nwpp)}q_P!m{twRY2zYbeB;~4mei-(SZ3V(b$`xKN7b7`SWpI-j@Ki)f9 zrk|v}F8JWfkyHJw-*0HPm-Ehqt|Q+RT%K1uk;he{?|cFaZgJ9ZSkqA>%(E2Xb4r_( zx?X{Q<)f3GRF7`<3oyn%M$Uo^Z-7g%def~-M9!G`h`o|~h&|1QRFXWG{r)zqCxUx_ zOnugfG(F3%={(R`|D?j-(As*vM_^Z>~r z>PjG@sLH<$$B#u*TRcKt@O%o1HIycg!%WW~Ja)lhlYxGoIzH-X0A7Ra5Pyv!{t9~h zQy}|bB@6}5p~;g!0jFhh_5e3w0G*B@z{@ZImj`D+wHP7a43O~H=3~1VHejR~poE?w zlwYU=^q1H7YrRjP?l9(i;QbJFwUXg`epvSDyWfiot)_1BSX*CA-7NpXuCl)Zf9Fs0 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/j_h.png b/assets/cards/faces/j_h.png new file mode 100644 index 0000000000000000000000000000000000000000..bb03374bdeca89422cd77c574f3a044d92b6dcf0 GIT binary patch literal 5009 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 W^?u?EK%CDRYhF!QUHQs~`~Lxy>{np` literal 0 HcmV?d00001 diff --git a/assets/cards/faces/k_s.png b/assets/cards/faces/k_s.png new file mode 100644 index 0000000000000000000000000000000000000000..c9c72f3201f5a2911454545dfc69e23d5fc73fd3 GIT binary patch literal 6148 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 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/q_c.png b/assets/cards/faces/q_c.png new file mode 100644 index 0000000000000000000000000000000000000000..b0cdfcbf076986e4d4b1cd445d5e8d2b1b048835 GIT binary patch literal 6388 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 literal 0 HcmV?d00001 diff --git a/assets/cards/faces/q_d.png b/assets/cards/faces/q_d.png new file mode 100644 index 0000000000000000000000000000000000000000..1766d6037fe743bbabd08f757f7dc17651210e4b GIT binary patch literal 6301 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 LFIO*lZ^z#OU@8u` literal 0 HcmV?d00001 diff --git a/assets/cards/faces/q_s.png b/assets/cards/faces/q_s.png new file mode 100644 index 0000000000000000000000000000000000000000..3d8a04891d3fc63b7beb719987efc58c0d6f6f5f GIT binary patch literal 6379 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 literal 0 HcmV?d00001 diff --git a/solitaire_assetgen/Cargo.toml b/solitaire_assetgen/Cargo.toml index 2b69fd0..60a3d81 100644 --- a/solitaire_assetgen/Cargo.toml +++ b/solitaire_assetgen/Cargo.toml @@ -10,7 +10,8 @@ publish = false # Not depended on by any other workspace crate. [dependencies] -png = "0.17" +png = "0.17" +ab_glyph = "0.2" [[bin]] name = "gen_sfx" diff --git a/solitaire_assetgen/src/bin/gen_art.rs b/solitaire_assetgen/src/bin/gen_art.rs index 551e1a1..f084f33 100644 --- a/solitaire_assetgen/src/bin/gen_art.rs +++ b/solitaire_assetgen/src/bin/gen_art.rs @@ -1,178 +1,418 @@ -//! Generates placeholder PNG assets for card faces, card backs, and table -//! backgrounds. All images are 16×16 pixels — Bevy's Sprite scales them via -//! `custom_size`, so small files keep the repository lightweight. +//! Generates PNG assets for Solitaire Quest. //! -//! Run with: -//! ``` -//! cargo run -p solitaire_assetgen --bin gen_art -//! ``` +//! Produces: +//! - 52 card face PNGs (120×168) — one per card, with rank, suit symbol, and +//! pip or face-letter layout baked in. +//! - 5 card back PNGs (16×16 placeholder patterns). +//! - 5 background PNGs (16×16 placeholder patterns). +//! +//! Run with: `cargo run -p solitaire_assetgen --bin gen_art` +use ab_glyph::{Font, FontRef, PxScale, ScaleFont}; use std::fs::File; use std::io::BufWriter; use std::path::Path; // --------------------------------------------------------------------------- -// PNG helper +// Card dimensions and palette // --------------------------------------------------------------------------- -/// Write a 16×16 RGBA image to `path`. `pixels` is a flat `[R,G,B,A, ...]` -/// byte array with exactly 16 * 16 * 4 = 1024 bytes. -fn save_png(path: &Path, pixels: &[u8; 1024]) { +const W: u32 = 120; +const H: u32 = 168; + +const BG: [u8; 4] = [0xFE, 0xFE, 0xF2, 0xFF]; +const BORDER: [u8; 4] = [0x99, 0x99, 0x99, 0xFF]; +const RED: [u8; 4] = [0xCC, 0x11, 0x11, 0xFF]; +const DARK: [u8; 4] = [0x11, 0x11, 0x11, 0xFF]; + +fn suit_color(suit: u8) -> [u8; 4] { + if suit == 1 || suit == 2 { RED } else { DARK } +} + +fn rank_str(rank: u8) -> &'static str { + ["A","2","3","4","5","6","7","8","9","10","J","Q","K"][rank as usize] +} + +// --------------------------------------------------------------------------- +// Pixel canvas (120×168 RGBA) +// --------------------------------------------------------------------------- + +struct Canvas { + data: Vec, +} + +impl Canvas { + fn new() -> Self { + let mut data = vec![0u8; (W * H * 4) as usize]; + for i in 0..(W * H) as usize { + data[i * 4..i * 4 + 4].copy_from_slice(&BG); + } + Self { data } + } + + fn set(&mut self, x: i32, y: i32, c: [u8; 4]) { + if x < 0 || y < 0 || x >= W as i32 || y >= H as i32 { return; } + let i = (y as u32 * W + x as u32) as usize * 4; + let a = c[3] as f32 / 255.0; + if a >= 0.99 { + self.data[i..i + 4].copy_from_slice(&c); + } else if a > 0.01 { + self.data[i] = (self.data[i] as f32 * (1.0 - a) + c[0] as f32 * a) as u8; + self.data[i + 1] = (self.data[i + 1] as f32 * (1.0 - a) + c[1] as f32 * a) as u8; + self.data[i + 2] = (self.data[i + 2] as f32 * (1.0 - a) + c[2] as f32 * a) as u8; + self.data[i + 3] = 255; + } + } + + fn circle(&mut self, cx: f32, cy: f32, r: f32, c: [u8; 4]) { + for y in (cy - r - 1.0) as i32..=(cy + r + 1.0) as i32 { + for x in (cx - r - 1.0) as i32..=(cx + r + 1.0) as i32 { + if (x as f32 - cx).powi(2) + (y as f32 - cy).powi(2) <= r * r { + self.set(x, y, c); + } + } + } + } + + fn fill_rect(&mut self, x: i32, y: i32, w: i32, h: i32, c: [u8; 4]) { + for ry in y..y + h { + for rx in x..x + w { + self.set(rx, ry, c); + } + } + } + + fn triangle(&mut self, pts: [(f32, f32); 3], c: [u8; 4]) { + let min_x = pts.iter().map(|p| p.0).fold(f32::INFINITY, f32::min) as i32; + let max_x = pts.iter().map(|p| p.0).fold(f32::NEG_INFINITY, f32::max) as i32; + let min_y = pts.iter().map(|p| p.1).fold(f32::INFINITY, f32::min) as i32; + let max_y = pts.iter().map(|p| p.1).fold(f32::NEG_INFINITY, f32::max) as i32; + let (ax, ay) = pts[0]; + let (bx, by) = pts[1]; + let (ex, ey) = pts[2]; + for y in min_y..=max_y { + for x in min_x..=max_x { + let px = x as f32 + 0.5; + let py = y as f32 + 0.5; + let d0 = (bx - ax) * (py - ay) - (by - ay) * (px - ax); + let d1 = (ex - bx) * (py - by) - (ey - by) * (px - bx); + let d2 = (ax - ex) * (py - ey) - (ay - ey) * (px - ex); + let neg = d0 < 0.0 || d1 < 0.0 || d2 < 0.0; + let pos = d0 > 0.0 || d1 > 0.0 || d2 > 0.0; + if !(neg && pos) { + self.set(x, y, c); + } + } + } + } + + fn diamond(&mut self, cx: f32, cy: f32, rx: f32, ry: f32, c: [u8; 4]) { + for y in (cy - ry - 1.0) as i32..=(cy + ry + 1.0) as i32 { + for x in (cx - rx - 1.0) as i32..=(cx + rx + 1.0) as i32 { + let nx = (x as f32 - cx).abs() / rx; + let ny = (y as f32 - cy).abs() / ry; + if nx + ny <= 1.0 { + self.set(x, y, c); + } + } + } + } +} + +// --------------------------------------------------------------------------- +// Suit symbol drawing +// --------------------------------------------------------------------------- + +fn draw_suit(cv: &mut Canvas, cx: f32, cy: f32, sz: f32, suit: u8, c: [u8; 4]) { + match suit { + 0 => draw_club(cv, cx, cy, sz, c), + 1 => draw_diamond_sym(cv, cx, cy, sz, c), + 2 => draw_heart(cv, cx, cy, sz, c), + _ => draw_spade(cv, cx, cy, sz, c), + } +} + +fn draw_heart(cv: &mut Canvas, cx: f32, cy: f32, sz: f32, c: [u8; 4]) { + let r = sz * 0.33; + let oy = cy - sz * 0.04; + cv.circle(cx - sz * 0.22, oy, r, c); + cv.circle(cx + sz * 0.22, oy, r, c); + cv.triangle([ + (cx - sz * 0.52, oy + r * 0.4), + (cx + sz * 0.52, oy + r * 0.4), + (cx, cy + sz * 0.52), + ], c); +} + +fn draw_spade(cv: &mut Canvas, cx: f32, cy: f32, sz: f32, c: [u8; 4]) { + cv.triangle([ + (cx, cy - sz * 0.52), + (cx - sz * 0.52, cy + sz * 0.1), + (cx + sz * 0.52, cy + sz * 0.1), + ], c); + cv.circle(cx - sz * 0.22, cy + sz * 0.06, sz * 0.3, c); + cv.circle(cx + sz * 0.22, cy + sz * 0.06, sz * 0.3, c); + // stem + base + cv.triangle([ + (cx, cy + sz * 0.12), + (cx - sz * 0.13, cy + sz * 0.5), + (cx + sz * 0.13, cy + sz * 0.5), + ], c); + cv.fill_rect( + (cx - sz * 0.26) as i32, + (cy + sz * 0.43) as i32, + (sz * 0.52) as i32, + (sz * 0.1) as i32, + c, + ); +} + +fn draw_diamond_sym(cv: &mut Canvas, cx: f32, cy: f32, sz: f32, c: [u8; 4]) { + cv.diamond(cx, cy, sz * 0.44, sz * 0.57, c); +} + +fn draw_club(cv: &mut Canvas, cx: f32, cy: f32, sz: f32, c: [u8; 4]) { + let r = sz * 0.29; + cv.circle(cx, cy - sz * 0.22, r, c); + cv.circle(cx - sz * 0.28, cy + sz * 0.1, r, c); + cv.circle(cx + sz * 0.28, cy + sz * 0.1, r, c); + cv.fill_rect( + (cx - sz * 0.08) as i32, + (cy + sz * 0.22) as i32, + (sz * 0.16) as i32 + 1, + (sz * 0.27) as i32, + c, + ); + cv.fill_rect( + (cx - sz * 0.26) as i32, + (cy + sz * 0.45) as i32, + (sz * 0.52) as i32, + (sz * 0.09) as i32, + c, + ); +} + +// --------------------------------------------------------------------------- +// Text rendering via ab_glyph +// --------------------------------------------------------------------------- + +fn draw_text(cv: &mut Canvas, font: &FontRef<'_>, text: &str, px: f32, left: f32, top: f32, c: [u8; 4]) { + let scale = PxScale::from(px); + let baseline = top + font.as_scaled(scale).ascent(); + let mut x = left; + for ch in text.chars() { + let gid = font.glyph_id(ch); + let glyph = gid.with_scale_and_position(scale, ab_glyph::point(x, baseline)); + let adv = font.as_scaled(scale).h_advance(gid); + if let Some(outlined) = font.outline_glyph(glyph) { + let bounds = outlined.px_bounds(); + outlined.draw(|gx, gy, cov| { + if cov > 0.02 { + let alpha = (cov * c[3] as f32) as u8; + cv.set( + (bounds.min.x + gx as f32) as i32, + (bounds.min.y + gy as f32) as i32, + [c[0], c[1], c[2], alpha], + ); + } + }); + } + x += adv; + } +} + +fn text_w(font: &FontRef<'_>, text: &str, px: f32) -> f32 { + let scale = PxScale::from(px); + let sf = font.as_scaled(scale); + text.chars().map(|c| sf.h_advance(font.glyph_id(c))).sum() +} + +fn text_h(font: &FontRef<'_>, px: f32) -> f32 { + let scale = PxScale::from(px); + let sf = font.as_scaled(scale); + sf.ascent() - sf.descent() +} + +// --------------------------------------------------------------------------- +// Pip layout (rank 0=Ace … 9=Ten; rank 10-12 are face cards) +// --------------------------------------------------------------------------- + +fn pip_positions(rank: u8) -> &'static [(f32, f32)] { + match rank { + 0 => &[(0.5, 0.5)], + 1 => &[(0.5, 0.2), (0.5, 0.8)], + 2 => &[(0.5, 0.12), (0.5, 0.5), (0.5, 0.88)], + 3 => &[(0.25, 0.18), (0.75, 0.18), (0.25, 0.82), (0.75, 0.82)], + 4 => &[(0.25, 0.18), (0.75, 0.18), (0.5, 0.5), (0.25, 0.82), (0.75, 0.82)], + 5 => &[(0.25, 0.12), (0.75, 0.12), (0.25, 0.5), (0.75, 0.5), (0.25, 0.88), (0.75, 0.88)], + 6 => &[(0.25, 0.1), (0.75, 0.1), (0.5, 0.31), (0.25, 0.5), (0.75, 0.5), (0.25, 0.9), (0.75, 0.9)], + 7 => &[(0.25, 0.1), (0.75, 0.1), (0.5, 0.28), (0.25, 0.48), (0.75, 0.48), (0.5, 0.70), (0.25, 0.9), (0.75, 0.9)], + 8 => &[(0.25, 0.1), (0.75, 0.1), (0.25, 0.35), (0.75, 0.35), (0.5, 0.5), (0.25, 0.65), (0.75, 0.65), (0.25, 0.9), (0.75, 0.9)], + 9 => &[(0.25, 0.09), (0.75, 0.09), (0.5, 0.27), (0.25, 0.44), (0.75, 0.44), (0.25, 0.56), (0.75, 0.56), (0.5, 0.73), (0.25, 0.91), (0.75, 0.91)], + _ => &[], + } +} + +// Pip area within the card (avoids the corner labels). +const PIP_X: f32 = 22.0; +const PIP_Y: f32 = 46.0; +const PIP_W: f32 = 76.0; +const PIP_H: f32 = 80.0; + +// --------------------------------------------------------------------------- +// Card face generation +// --------------------------------------------------------------------------- + +fn make_card_face(font: &FontRef<'_>, rank: u8, suit: u8) -> Canvas { + let mut cv = Canvas::new(); + let sc = suit_color(suit); + + // Border (2 px) + for x in 0..W as i32 { + cv.set(x, 0, BORDER); + cv.set(x, 1, BORDER); + cv.set(x, H as i32 - 2, BORDER); + cv.set(x, H as i32 - 1, BORDER); + } + for y in 0..H as i32 { + cv.set(0, y, BORDER); + cv.set(1, y, BORDER); + cv.set(W as i32 - 2, y, BORDER); + cv.set(W as i32 - 1, y, BORDER); + } + + let rank_s = rank_str(rank); + let rank_px = 18.0f32; + let suit_sz = 11.0f32; + let rh = text_h(font, rank_px); + let rw = text_w(font, rank_s, rank_px); + let corner_h = rh + 2.0 + suit_sz * 1.5; + + // Top-left corner + let tl_x = 6.0f32; + let tl_y = 5.0f32; + draw_text(&mut cv, font, rank_s, rank_px, tl_x, tl_y, sc); + draw_suit(&mut cv, tl_x + suit_sz * 0.62, tl_y + rh + 2.0 + suit_sz * 0.75, suit_sz, suit, sc); + + // Bottom-right corner (right-aligned rank, suit above it) + let br_rx = W as f32 - 6.0; + let br_by = H as f32 - 5.0; + let br_ty = br_by - corner_h; + draw_text(&mut cv, font, rank_s, rank_px, br_rx - rw, br_ty, sc); + draw_suit(&mut cv, br_rx - suit_sz * 0.62, br_ty + rh + 2.0 + suit_sz * 0.75, suit_sz, suit, sc); + + // Center content + if rank >= 10 { + // Face cards: large rank letter + suit symbol below + let big_px = 52.0f32; + let big_w = text_w(font, rank_s, big_px); + let big_h = text_h(font, big_px); + let big_x = (W as f32 - big_w) / 2.0; + let big_y = H as f32 * 0.28; + draw_text(&mut cv, font, rank_s, big_px, big_x, big_y, sc); + let sym_sz = 22.0f32; + draw_suit(&mut cv, W as f32 * 0.5, big_y + big_h + sym_sz * 1.0, sym_sz, suit, sc); + } else { + // Pip cards + let pip_sz = if rank == 0 { + 24.0f32 // Ace: large single pip + } else if rank <= 5 { + 14.0 + } else { + 12.0 + }; + for &(nx, ny) in pip_positions(rank) { + let cx = PIP_X + nx * PIP_W; + let cy = PIP_Y + ny * PIP_H; + draw_suit(&mut cv, cx, cy, pip_sz, suit, sc); + } + } + + cv +} + +// --------------------------------------------------------------------------- +// PNG encoding helpers +// --------------------------------------------------------------------------- + +fn save_card_png(path: &Path, cv: &Canvas) { + save_png_wh(path, &cv.data, W, H); +} + +fn save_png_wh(path: &Path, data: &[u8], w: u32, h: u32) { let file = File::create(path) .unwrap_or_else(|e| panic!("cannot create {}: {e}", path.display())); - let mut w = BufWriter::new(file); - let mut encoder = png::Encoder::new(&mut w, 16, 16); - encoder.set_color(png::ColorType::Rgba); - encoder.set_depth(png::BitDepth::Eight); - let mut writer = encoder - .write_header() + let mut bw = BufWriter::new(file); + let mut enc = png::Encoder::new(&mut bw, w, h); + enc.set_color(png::ColorType::Rgba); + enc.set_depth(png::BitDepth::Eight); + let mut writer = enc.write_header() .unwrap_or_else(|e| panic!("png header error for {}: {e}", path.display())); - writer - .write_image_data(pixels) + writer.write_image_data(data) .unwrap_or_else(|e| panic!("png data error for {}: {e}", path.display())); } -/// Build a flat 16×16 RGBA pixel array using a per-pixel closure. -fn make_image [u8; 4]>(f: F) -> [u8; 1024] { - let mut pixels = [0u8; 1024]; +fn save_small_png(path: &Path, pixels: &[u8; 1024]) { + save_png_wh(path, pixels, 16, 16); +} + +fn make_small [u8; 4]>(f: F) -> [u8; 1024] { + let mut out = [0u8; 1024]; for y in 0u32..16 { for x in 0u32..16 { - let rgba = f(x, y); + let c = f(x, y); let i = ((y * 16 + x) * 4) as usize; - pixels[i..i + 4].copy_from_slice(&rgba); + out[i..i + 4].copy_from_slice(&c); } } - pixels + out } // --------------------------------------------------------------------------- -// Card face +// Card backs (16×16 placeholder patterns) // --------------------------------------------------------------------------- -/// Cream/ivory solid fill — represents a blank card face. -fn make_face() -> [u8; 1024] { - make_image(|_, _| [0xF8, 0xF8, 0xF0, 0xFF]) -} - -// --------------------------------------------------------------------------- -// Card backs (match the colours used in card_plugin.rs `card_back_colour()`) -// --------------------------------------------------------------------------- - -/// back_0 — blue base with semi-transparent white horizontal stripes every 4 px. fn make_back_0() -> [u8; 1024] { - make_image(|_, y| { - if y % 4 < 2 { - [0xFF, 0xFF, 0xFF, 40] - } else { - [0x26, 0x4D, 0x8C, 0xFF] - } - }) + make_small(|_, y| if y % 4 < 2 { [0xFF, 0xFF, 0xFF, 40] } else { [0x26, 0x4D, 0x8C, 0xFF] }) } - -/// back_1 — red base with semi-transparent white diagonal stripes. fn make_back_1() -> [u8; 1024] { - make_image(|x, y| { - if (x + y) % 4 < 2 { - [0xFF, 0xFF, 0xFF, 40] - } else { - [0x8C, 0x1A, 0x1A, 0xFF] - } - }) + make_small(|x, y| if (x + y) % 4 < 2 { [0xFF, 0xFF, 0xFF, 40] } else { [0x8C, 0x1A, 0x1A, 0xFF] }) } - -/// back_2 — green base with white dots at every 4-px grid intersection. fn make_back_2() -> [u8; 1024] { - make_image(|x, y| { - if x % 4 == 0 && y % 4 == 0 { - [0xFF, 0xFF, 0xFF, 0xFF] - } else { - [0x0D, 0x66, 0x1A, 0xFF] - } - }) + make_small(|x, y| if x.is_multiple_of(4) && y.is_multiple_of(4) { [0xFF, 0xFF, 0xFF, 0xFF] } else { [0x0D, 0x66, 0x1A, 0xFF] }) } - -/// back_3 — purple base with a white diamond centred at (8, 8). fn make_back_3() -> [u8; 1024] { - make_image(|x, y| { + make_small(|x, y| { let dx = (x as i32 - 8).unsigned_abs(); let dy = (y as i32 - 8).unsigned_abs(); - if dx + dy <= 4 { - [0xFF, 0xFF, 0xFF, 0xFF] - } else { - [0x59, 0x14, 0x85, 0xFF] - } + if dx + dy <= 4 { [0xFF, 0xFF, 0xFF, 0xFF] } else { [0x59, 0x14, 0x85, 0xFF] } }) } - -/// back_4 — teal base with a 1-px white border. fn make_back_4() -> [u8; 1024] { - make_image(|x, y| { - if x == 0 || x == 15 || y == 0 || y == 15 { - [0xFF, 0xFF, 0xFF, 0xFF] - } else { - [0x0D, 0x66, 0x6B, 0xFF] - } - }) + make_small(|x, y| if x == 0 || x == 15 || y == 0 || y == 15 { [0xFF, 0xFF, 0xFF, 0xFF] } else { [0x0D, 0x66, 0x6B, 0xFF] }) } // --------------------------------------------------------------------------- -// Backgrounds +// Backgrounds (16×16 placeholder patterns) // --------------------------------------------------------------------------- -/// bg_0 — dark green felt with very faint lighter grid lines every 8 px. fn make_bg_0() -> [u8; 1024] { - make_image(|x, y| { - if x % 8 == 0 || y % 8 == 0 { - [0xFF, 0xFF, 0xFF, 30] - } else { - [0x1A, 0x4D, 0x1A, 0xFF] - } - }) + make_small(|x, y| if x.is_multiple_of(8) || y.is_multiple_of(8) { [0xFF, 0xFF, 0xFF, 30] } else { [0x1A, 0x4D, 0x1A, 0xFF] }) } - -/// bg_1 — dark wood brown with faint horizontal grain lines every 2 px. fn make_bg_1() -> [u8; 1024] { - make_image(|_, y| { - if y % 2 == 0 { - [0xFF, 0xFF, 0xFF, 20] - } else { - [0x40, 0x2D, 0x1A, 0xFF] - } - }) + make_small(|_, y| if y.is_multiple_of(2) { [0xFF, 0xFF, 0xFF, 20] } else { [0x40, 0x2D, 0x1A, 0xFF] }) } - -/// bg_2 — navy with faint star/dot pattern (offset rows) every 8 px. fn make_bg_2() -> [u8; 1024] { - make_image(|x, y| { - let row_offset: u32 = if (y / 4) % 2 == 0 { 0 } else { 4 }; - if (x + row_offset) % 8 == 0 && y % 8 == 0 { - [0xFF, 0xFF, 0xFF, 0xFF] - } else { - [0x0D, 0x14, 0x38, 0xFF] - } + make_small(|x, y| { + let off: u32 = if (y / 4).is_multiple_of(2) { 0 } else { 4 }; + if (x + off).is_multiple_of(8) && y.is_multiple_of(8) { [0xFF, 0xFF, 0xFF, 0xFF] } else { [0x0D, 0x14, 0x38, 0xFF] } }) } - -/// bg_3 — burgundy with a faint diamond-grid pattern. fn make_bg_3() -> [u8; 1024] { - make_image(|x, y| { - if (x + y) % 8 == 0 { - [0xFF, 0xFF, 0xFF, 30] - } else { - [0x4D, 0x0D, 0x14, 0xFF] - } - }) + make_small(|x, y| if (x + y).is_multiple_of(8) { [0xFF, 0xFF, 0xFF, 30] } else { [0x4D, 0x0D, 0x14, 0xFF] }) } - -/// bg_4 — charcoal with faint pixel noise (alternating pixels every 3 columns). fn make_bg_4() -> [u8; 1024] { - make_image(|x, y| { - if (x + y) % 2 == 0 && x % 3 == 0 { - [0xFF, 0xFF, 0xFF, 20] - } else { - [0x1F, 0x1F, 0x24, 0xFF] - } - }) + make_small(|x, y| if (x + y).is_multiple_of(2) && x.is_multiple_of(3) { [0xFF, 0xFF, 0xFF, 20] } else { [0x1F, 0x1F, 0x24, 0xFF] }) } // --------------------------------------------------------------------------- @@ -186,44 +426,43 @@ fn workspace_root() -> std::path::PathBuf { fn main() { let root = workspace_root(); - - // Ensure output directories exist. std::fs::create_dir_all(root.join("assets/cards/faces")).unwrap(); std::fs::create_dir_all(root.join("assets/cards/backs")).unwrap(); std::fs::create_dir_all(root.join("assets/backgrounds")).unwrap(); - // Card face. - let path = root.join("assets/cards/faces/face.png"); - save_png(&path, &make_face()); - println!("wrote {}", path.display()); + // Load font from disk (dev tool — runtime load is fine here). + let font_path = root.join("assets/fonts/main.ttf"); + let font_bytes = std::fs::read(&font_path) + .unwrap_or_else(|e| panic!("failed to read {}: {e}", font_path.display())); + let font = FontRef::try_from_slice(&font_bytes) + .expect("failed to parse assets/fonts/main.ttf"); - // Card backs. - let backs = [ - make_back_0(), - make_back_1(), - make_back_2(), - make_back_3(), - make_back_4(), - ]; - for (i, pixels) in backs.iter().enumerate() { + // 52 card faces + let suits = ["c", "d", "h", "s"]; + let ranks = ["a","2","3","4","5","6","7","8","9","10","j","q","k"]; + for suit in 0u8..4 { + for rank in 0u8..13 { + let cv = make_card_face(&font, rank, suit); + let name = format!("{}_{}.png", ranks[rank as usize], suits[suit as usize]); + let path = root.join("assets/cards/faces").join(&name); + save_card_png(&path, &cv); + println!("wrote {}", path.display()); + } + } + + // Card backs + for (i, pixels) in [make_back_0(), make_back_1(), make_back_2(), make_back_3(), make_back_4()].iter().enumerate() { let path = root.join(format!("assets/cards/backs/back_{i}.png")); - save_png(&path, pixels); + save_small_png(&path, pixels); println!("wrote {}", path.display()); } - // Backgrounds. - let bgs = [ - make_bg_0(), - make_bg_1(), - make_bg_2(), - make_bg_3(), - make_bg_4(), - ]; - for (i, pixels) in bgs.iter().enumerate() { + // Backgrounds + for (i, pixels) in [make_bg_0(), make_bg_1(), make_bg_2(), make_bg_3(), make_bg_4()].iter().enumerate() { let path = root.join(format!("assets/backgrounds/bg_{i}.png")); - save_png(&path, pixels); + save_small_png(&path, pixels); println!("wrote {}", path.display()); } - println!("gen_art: all placeholder PNG assets generated successfully."); + println!("gen_art: all assets generated successfully."); } diff --git a/solitaire_assetgen/src/bin/gen_sfx.rs b/solitaire_assetgen/src/bin/gen_sfx.rs index a64395f..6548315 100644 --- a/solitaire_assetgen/src/bin/gen_sfx.rs +++ b/solitaire_assetgen/src/bin/gen_sfx.rs @@ -25,8 +25,8 @@ fn main() -> io::Result<()> { ("ambient_loop.wav", ambient_loop), ]; - for (name, gen) in &effects { - let samples = gen(); + for (name, make) in &effects { + let samples = make(); let path = out_dir.join(name); write_wav_mono_pcm16(&path, SAMPLE_RATE, &samples)?; println!("wrote {} ({} samples)", path.display(), samples.len()); diff --git a/solitaire_engine/src/card_plugin.rs b/solitaire_engine/src/card_plugin.rs index 6be71d9..46033d0 100644 --- a/solitaire_engine/src/card_plugin.rs +++ b/solitaire_engine/src/card_plugin.rs @@ -54,8 +54,11 @@ pub const BLACK_SUIT_COLOUR: Color = Color::srgb(0.08, 0.08, 0.08); /// solid-colour sprites (used in tests with `MinimalPlugins`). #[derive(Resource)] pub struct CardImageSet { - /// Shared face image used for all face-up cards. - pub face: Handle, + /// Per-card face images indexed by `[suit][rank]`. + /// + /// Suit order: Clubs=0, Diamonds=1, Hearts=2, Spades=3. + /// Rank order: Ace=0, Two=1 … King=12. + pub faces: [[Handle; 13]; 4], /// One handle per unlockable card-back design (indices 0–4). pub backs: [Handle; 5], } @@ -202,8 +205,6 @@ impl Plugin for CardPlugin { /// so it does nothing and the plugin falls back to solid-colour sprites. fn load_card_images(images: Option>>, mut commands: Commands) { let Some(mut images) = images else { - // Assets is absent (e.g. MinimalPlugins in tests) — skip so - // tests can still run. The plugin falls back to solid-colour sprites. return; }; use bevy::asset::RenderAssetUsages; @@ -221,7 +222,79 @@ fn load_card_images(images: Option>>, mut commands: Command .expect("valid card PNG") }; - let face = images.add(load(include_bytes!("../../assets/cards/faces/face.png"))); + // 52 face images: faces[suit][rank] + // Suit: Clubs=0, Diamonds=1, Hearts=2, Spades=3 + // Rank: Ace=0 … King=12 + const FACE_BYTES: [[&[u8]; 13]; 4] = [ + // Clubs + [ + include_bytes!("../../assets/cards/faces/a_c.png"), + include_bytes!("../../assets/cards/faces/2_c.png"), + include_bytes!("../../assets/cards/faces/3_c.png"), + include_bytes!("../../assets/cards/faces/4_c.png"), + include_bytes!("../../assets/cards/faces/5_c.png"), + include_bytes!("../../assets/cards/faces/6_c.png"), + include_bytes!("../../assets/cards/faces/7_c.png"), + include_bytes!("../../assets/cards/faces/8_c.png"), + include_bytes!("../../assets/cards/faces/9_c.png"), + include_bytes!("../../assets/cards/faces/10_c.png"), + include_bytes!("../../assets/cards/faces/j_c.png"), + include_bytes!("../../assets/cards/faces/q_c.png"), + include_bytes!("../../assets/cards/faces/k_c.png"), + ], + // Diamonds + [ + include_bytes!("../../assets/cards/faces/a_d.png"), + include_bytes!("../../assets/cards/faces/2_d.png"), + include_bytes!("../../assets/cards/faces/3_d.png"), + include_bytes!("../../assets/cards/faces/4_d.png"), + include_bytes!("../../assets/cards/faces/5_d.png"), + include_bytes!("../../assets/cards/faces/6_d.png"), + include_bytes!("../../assets/cards/faces/7_d.png"), + include_bytes!("../../assets/cards/faces/8_d.png"), + include_bytes!("../../assets/cards/faces/9_d.png"), + include_bytes!("../../assets/cards/faces/10_d.png"), + include_bytes!("../../assets/cards/faces/j_d.png"), + include_bytes!("../../assets/cards/faces/q_d.png"), + include_bytes!("../../assets/cards/faces/k_d.png"), + ], + // Hearts + [ + include_bytes!("../../assets/cards/faces/a_h.png"), + include_bytes!("../../assets/cards/faces/2_h.png"), + include_bytes!("../../assets/cards/faces/3_h.png"), + include_bytes!("../../assets/cards/faces/4_h.png"), + include_bytes!("../../assets/cards/faces/5_h.png"), + include_bytes!("../../assets/cards/faces/6_h.png"), + include_bytes!("../../assets/cards/faces/7_h.png"), + include_bytes!("../../assets/cards/faces/8_h.png"), + include_bytes!("../../assets/cards/faces/9_h.png"), + include_bytes!("../../assets/cards/faces/10_h.png"), + include_bytes!("../../assets/cards/faces/j_h.png"), + include_bytes!("../../assets/cards/faces/q_h.png"), + include_bytes!("../../assets/cards/faces/k_h.png"), + ], + // Spades + [ + include_bytes!("../../assets/cards/faces/a_s.png"), + include_bytes!("../../assets/cards/faces/2_s.png"), + include_bytes!("../../assets/cards/faces/3_s.png"), + include_bytes!("../../assets/cards/faces/4_s.png"), + include_bytes!("../../assets/cards/faces/5_s.png"), + include_bytes!("../../assets/cards/faces/6_s.png"), + include_bytes!("../../assets/cards/faces/7_s.png"), + include_bytes!("../../assets/cards/faces/8_s.png"), + include_bytes!("../../assets/cards/faces/9_s.png"), + include_bytes!("../../assets/cards/faces/10_s.png"), + include_bytes!("../../assets/cards/faces/j_s.png"), + include_bytes!("../../assets/cards/faces/q_s.png"), + include_bytes!("../../assets/cards/faces/k_s.png"), + ], + ]; + + let faces: [[Handle; 13]; 4] = std::array::from_fn(|suit| { + std::array::from_fn(|rank| images.add(load(FACE_BYTES[suit][rank]))) + }); let backs = [ images.add(load(include_bytes!("../../assets/cards/backs/back_0.png"))), images.add(load(include_bytes!("../../assets/cards/backs/back_1.png"))), @@ -229,7 +302,7 @@ fn load_card_images(images: Option>>, mut commands: Command images.add(load(include_bytes!("../../assets/cards/backs/back_3.png"))), images.add(load(include_bytes!("../../assets/cards/backs/back_4.png"))), ]; - commands.insert_resource(CardImageSet { face, backs }); + commands.insert_resource(CardImageSet { faces, backs }); } /// Builds the [`Sprite`] for a card, using PNG artwork when [`CardImageSet`] is @@ -244,7 +317,28 @@ fn card_sprite( ) -> Sprite { if let Some(set) = card_images { let image = if card.face_up { - set.face.clone() + let suit_idx = match card.suit { + Suit::Clubs => 0, + Suit::Diamonds => 1, + Suit::Hearts => 2, + Suit::Spades => 3, + }; + let rank_idx = match card.rank { + Rank::Ace => 0, + Rank::Two => 1, + Rank::Three => 2, + Rank::Four => 3, + Rank::Five => 4, + Rank::Six => 5, + Rank::Seven => 6, + Rank::Eight => 7, + Rank::Nine => 8, + Rank::Ten => 9, + Rank::Jack => 10, + Rank::Queen => 11, + Rank::King => 12, + }; + set.faces[suit_idx][rank_idx].clone() } else { let idx = selected_back.min(set.backs.len() - 1); set.backs[idx].clone() @@ -462,14 +556,16 @@ fn spawn_card_entity( ) { let sprite = card_sprite(card, layout.card_size, back_colour, color_blind, card_images, selected_back); - commands - .spawn(( - CardEntity { card_id: card.id }, - sprite, - Transform::from_xyz(pos.x, pos.y, z), - Visibility::default(), - )) - .with_children(|b| { + let mut entity = commands.spawn(( + CardEntity { card_id: card.id }, + sprite, + Transform::from_xyz(pos.x, pos.y, z), + Visibility::default(), + )); + // When PNG faces are loaded the rank/suit are baked into the image. + // Only spawn the Text2d overlay in the solid-colour fallback (tests). + if card_images.is_none() { + entity.with_children(|b| { b.spawn(( CardLabel, Text2d::new(label_for(card)), @@ -478,12 +574,11 @@ fn spawn_card_entity( ..default() }, TextColor(text_colour(card)), - // Above the card body on z so it doesn't get occluded by the - // parent sprite in back-to-front rendering. Transform::from_xyz(0.0, 0.0, 0.01), label_visibility(card), )); }); + } } #[allow(clippy::too_many_arguments)] @@ -526,22 +621,25 @@ fn update_card_entity( .insert(Transform::from_xyz(pos.x, pos.y, z)); } - // Despawn the old label child and respawn a fresh one, so rank/suit/ - // colour/visibility all stay in sync with the card's current state. + // Despawn any stale children and re-add the label overlay only when + // operating in solid-colour mode (no PNG faces). In image mode the + // rank/suit are baked into the PNG, so no Text2d overlay is needed. commands.entity(entity).despawn_related::(); - commands.entity(entity).with_children(|b| { - b.spawn(( - CardLabel, - Text2d::new(label_for(card)), - TextFont { - font_size: layout.card_size.x * FONT_SIZE_FRAC, - ..default() - }, - TextColor(text_colour(card)), - Transform::from_xyz(0.0, 0.0, 0.01), - label_visibility(card), - )); - }); + if card_images.is_none() { + commands.entity(entity).with_children(|b| { + b.spawn(( + CardLabel, + Text2d::new(label_for(card)), + TextFont { + font_size: layout.card_size.x * FONT_SIZE_FRAC, + ..default() + }, + TextColor(text_colour(card)), + Transform::from_xyz(0.0, 0.0, 0.01), + label_visibility(card), + )); + }); + } } fn label_for(card: &Card) -> String {