ó
    RçÛjC  ã                   óŽ  • S r SSKrSSKrSSKrSSKrSSKrSSKrSSKr\R                  R                  \R                  R                  \5      5      r\R                  R                  S\5        SSKrSSKJr  SSKr\R&                  r\R(                  R+                  \5      r\R                  R/                  \S5      r\R                  R/                  \S5      rS*S jrS+S	 jrS
 rS,S jr\S:X  Ga(  \R>                  " 5       r \ RC                  S\"SS9  \ RC                  S\"SS9  \ RC                  S\"SS9  \ RC                  SSS9  \ RG                  5       r$\$R8                  (       a'  \" 5       r%\&" \'" \%5      S5        \RP                  " 5         \)" 5       r*\R                  RW                  \5      (       a3  \," \5       H'  r-\*R]                  \R^                  " \-5      S   5        M)     \1" \R                  " \R                  R/                  \SSS5      5      \R                  Rd                  SS9r3\3 V s/ s H‰  n \R                  Ri                  \R                  R                  U 5      5      \*;  d  M=  \R                  Ri                  \R                  R                  U 5      5      Rk                  S5      (       a  M‡  U PM‹     sn r3\$Rf                  (       a  \3S\$Rf                   r3\," \S5       r6\7" \35       GH  u  r8r9\R                  Ri                  \R                  R                  \95      5      r:\R
                  " 5       r;\" \9\8S9r<\<c  \&" \:S5        Ma  \" \<\:\$Rz                  \$R|                  \R~                  R�                  \85      \65      rA\&" \: S\'" \<R…                  5       5       S \'" \A Vs1 s H  oS!   US"   4iM     sn5       S#\C" S$ \A 5       5       S%\'" \A5       S&\R
                  " 5       \;-
  S' S(3SS)9  GM     SSS5        \" 5         gg! \0 a     GMh  f = fs  sn f s  snf ! , (       d  f       N/= f)-a²  fits.py -- the fit bot: offline, free, no Opus. It loads boards Pin really played, tries pieces from Pin's bin on their open
spots, and writes down what actually fits (Ivy, Oct 23 2026: "We should have a bot that try fitting stuff together randomly from
played boards to try to which parts fit together best... Someway to offline learn for free what pieces Fit with which so it can
get handed a piece that will at least fit when it's stuck... so it can choose from legal smart choices without having to even
think about the dumb ones").

Every try goes through the game's own engine (play.Reef.try_move: real connectors, the sampled-surface collision check, the
invisible baseplate), so "fits" here means exactly what it means in a game. Results append to fits.jsonl one line per
(board, open spot, piece), so a run can be stopped and resumed; table() folds them into fits.json:
    host part -> connector kind -> piece -> [fitted, tried]

    python3 fits.py --boards 1 --spots 6        # a timing run
    python3 fits.py                              # every saved board not yet swept (run it at idle priority)
    python3 fits.py --table                      # just rebuild fits.json
Written by Iris.é    N)ÚGz
fits.jsonlz	fits.jsonc           	      ó  • [         R                  " US[        R                  R	                  [
        SS5      5      nUR                  R                  R                  R                  5         [        U 5       GH‡  nUR                  5       n[        U5      S:  d	  US   S:w  a  M.  US   R                  5       R                  S5      (       a  US   S	S
 OUS   nU[         R                  ;  a  U[         R                   ;  a  MŒ  ["        R$                  " S5      odSS  Vs/ s H  n['        U5      PM     snUS	S2S4'   ["        R(                  " USS  Vs/ s H  n['        U5      PM     sn5      R+                  SS5      US	S2S	S24'   [,        R.                  " U5      n[2        U-  [4        -  Ul        [9        US   5      Ul        SUl        UR                  R                  R                  R?                  U5        GMŠ     UR                  R                  R                  (       d  g	UR                  RA                  5         [         RB                  " URE                  5       5      S   Ul#        U$ s  snf s  snf ! [0         a     GM  f = f)zka saved .ldr back into a live board (the inverse of kit.write_ldr: it stores M = C^-1 T C, so T = C M C^-1)ÚtidyÚrunsÚ_fitsé   r   Ú1é   z.datNéüÿÿÿé   é   é   é   é   T)$ÚplayÚReefÚosÚpathÚjoinÚHEREÚgÚasmÚpartsÚclearÚopenÚsplitÚlenÚlowerÚendswithÚPALETTEÚ
BASEPLATESÚnpÚeyeÚfloatÚarrayÚreshaper   ÚfreshÚ	ExceptionÚCÚCiÚTÚintÚcolourÚattachedÚappendÚ	reconcileÚ
floor_gridÚbodiesÚ	floor_off)	ÚldrÚseedÚrÚlineÚfÚnameÚMÚvÚps	            Ú*/home/ivy/projects/brick_reef/reef/fits.pyÚ
load_boardr>      sÖ  € ä�	Š	�$˜¤§¡§¡¬T°6¸7Ó CÓD€AØ‡C�C‡G�G‡M�M×ÑÔÜ�S—	ˆØ�J‰J‹LˆÜˆq‹6�B‹;˜!˜A™$ #›+¡xØ˜r™UŸ[™[›]×3Ñ3°F×;Ñ;ˆq�‰u�S�b‰zÀÀ2ÁˆØ”t—|‘|Ó#¨´D·O±OÓ(CÁXÜ�FŠF�1‹Iˆ°q¸±VÓ"<²V°¤5¨¦8±VÑ"<�q˜˜!˜˜Q˜‘xÌ"Ï(Ê(ÐfgÐhiÐjlÑfmÓSnÒfmÐabÔTYÐZ[ÖT\ÑfmÑSnÓJo×JwÑJwÐxyÐ{|ÓJ}¸aÀÀÀÀBÀQÀBÀ¹iÜ—’˜“ˆQä�!‰e”b‰jˆŒ¤S¨¨1©£Y˜!œ(¸T°´
À1Ç3Á3Ç7Á7Ç=Á=×CWÑCWÐXY×CZñ ð �3‰3�7‰7�=�= Ø‡C�C‡M�M„O¤4§?¢?°1·8±8³:Ó#>¸qÑ#A�Q”[Ø€Hùò #=ùÒSnøäÓ"›(Ð"ús   ÄI/ÅI4
ÆI9É9
JÊJé   r   c                 ó†  • U=(       d    [         R                  R                  S5      nU R                  5        Vs/ s H  ofS   S:w  d  M  UPM     nn[	        U5      U:”  a,  UR                  [	        U5      USS9 Vs/ s H  o‡U   PM	     nn/ n	U GH   nUS   R                  n
[        R                   Hß  nSu  pÍ[        U5       H}  nUS-  nU R                  Xk[        UR                  S5      5      [        UR                  [        R                  5      5      5      nU(       d  Mb  U R                   R"                  " U6   Sn  O   XUS   X¼US	.nU	R%                  U5        U(       d  M·  UR'                  [(        R*                  " U5      S
-   5        Má     U(       d  GM  UR-                  5         GM#     U	$ s  snf s  snf )zçfor up to `spots` open spots on the board (never the bare floor: a piece on the floor fits trivially and joins nothing),
try every piece in the palette up to `ways` random ways (connector index, spin) and record the first that fitsr   ÚfloorF)Úreplacer   )Fr   é   T)ÚboardÚhostÚkindÚpieceÚokÚtriesÚ
)r"   ÚrandomÚdefault_rngÚconnsr   Úchoicer9   r   r    ÚrangeÚtry_mover,   Úintegersr$   r   ÚSPINSr   Úundor/   ÚwriteÚjsonÚdumpsÚflush)r6   rD   ÚspotsÚwaysÚrngÚoutÚcÚcsÚiÚrowsrE   r9   rH   ÚnÚ_ÚresÚrows                    r=   Úsweeprd   ,   sf  € ð ×
)”—‘×&Ñ& qÓ)€CØ—W‘W”YÓ	2’Y� A¡$¨'¡/�!‘Y€BÐ	2Ü
ˆ2ƒw�ƒ¨S¯Z©Z¼¸B»ÀÐPU¨ZÑ-VÓWÒ-V¨ œeÑ-V˜ÐWØ€DÜˆØ�‰t�y‰yˆÜ—L”LˆDØ‰EˆBÜ˜4–[�Ø�Q‘�Ø—j‘j ¬#¨c¯l©l¸1«oÓ*>ÄÀcÇjÁjÔQR×QXÑQXÓFYÓ@ZÓ[�ß�3˜Ÿ™Ÿš #™¨T¨±5ñ !ð "¸¸1¹ÈÐabÑcˆCØ�K‰K˜Ôßˆs�C—I‘IœdŸjšj¨›o°Ñ4Ö5ñ !÷ ‰3�—	‘	—ñ ð €Kùò 
3ùÚWs   »F9ÁF9Á>F>c                  óè  • 0 n [         R                  R                  [        5      (       d  U $ [	        [        5       H|  n[
        R                  " U5      nU R                  US   0 5      R                  US   0 5      R                  US   SS/5      nUS==   [        US   5      -  ss'   US==   S-  ss'   M~     [
        R                  " U [	        [        S5      5        U $ ! [         a     M´  f = f)NrE   rF   rG   r   rH   r   Úw)r   r   ÚexistsÚLOGr   rU   ÚloadsÚ
ValueErrorÚ
setdefaultr,   ÚdumpÚTABLE)ÚtÚlÚxÚes       r=   Útablerr   A   sÃ   € Ø
€AÜ�7‰7�>‰>œ#×Ñ q Ü”#ŽYˆÜ—’˜A“ˆQà�L‰L˜˜6™ BÓ'×2Ñ2°1°V±9¸bÓA×LÑLÈQÈwÉZÐZ[Ð]^ÐY_Ó`ˆØ	ˆ!‹”�A�d‘G“Ñ‹˜a ›d a™i�dñ	 ô
 	‡I‚Iˆa””e˜SÓ!Ô"Ø€Høô	 Ó#š8Ð#ús   ¿C#Ã#
C1Ã0C1c                 óú  • Ub  UOL[         R                  R                  [        5      (       a#  [        R
                  " [        [        5      5      O0 n0 nUR                  U 5      =(       d    0 R                  5        H\  u  pEU(       a  XA:w  a  M  UR                  5        H5  u  nu  pxUR                  USS/5      o™S==   U-  ss'   U	S==   U-  ss'   M7     M^     [        S UR                  5        5       S S9$ )zrpieces that have fitted onto this host part (optionally on one connector kind), best first: [(piece, rate, tried)]r   r   c              3   óL   #   • U  H  u  nu  p#U(       d  M  XU-  U4v •  M     g 7f)N© )Ú.0r<   Úar`   s       r=   Ú	<genexpr>Úfits_onto.<locals>.<genexpr>S   s"   é € ÐC²+¡Y Q©¨Ä“=�A˜1‘u˜a•=²+ùs   ‚$–$c                 ó   • U S   * $ )Nr   ru   )rp   s    r=   Ú<lambda>Úfits_onto.<locals>.<lambda>S   s   € ÐTUÐVWÑTXÑSXó    )Úkey)r   r   rg   rm   rU   Úloadr   ÚgetÚitemsrk   Úsorted)
rE   rF   rn   ÚaggÚkÚdr<   rw   r`   rq   s
             r=   Ú	fits_ontor†   L   s¸   € à‰]‰¼2¿7¹7¿>¹>Ì%×;PÑ;P¤§¢¬4´«;Ô!7ÐVX€AØ
€CØ—‘�t“×" ×)Ñ)Ö+‰ˆÞ�A“I™xØŸ™ž‰IˆA‰v�¨¯©°q¸1¸a¸&Ó(A AÀQÃ4È1Á9Ã4ÈaÐPQËdÐVWÉiÍd›ñ ,ô ÑC°#·)±)´+ÓCÉÑYÐYr}   Ú__main__z--boards)ÚtypeÚdefaultz--spotsz--waysz--tableÚ
store_true)Úactionzhost parts in fits.jsonrD   r   Ú*z	build.ldrT)r~   Úreversera   rw   )r5   znothing loadablez: z	 pieces, rE   rF   z spots, c              #   ó*   #   • U  H	  oS    v •  M     g7f)rH   Nru   )rv   rp   s     r=   rx   rx   h   s   é € Ð/ª$ Q˜4žª$ùs   ‚Ú/z fit, z.0fz s)rW   )r   )r?   r   NN)NN)DÚ__doc__r   ÚsysrU   ÚglobÚtimeÚargparseÚnumpyr"   r   ÚdirnameÚabspathÚ__file__r   Úinsertr   r   ÚbuildÚBr)   ÚlinalgÚinvr*   r   rh   rm   r>   rd   rr   r†   Ú__name__ÚArgumentParserÚapÚadd_argumentr,   Ú
parse_argsrw   rn   Úprintr   ÚexitÚsetÚdonerg   r   ro   Úaddri   rj   r‚   ÚgetmtimeÚboardsÚbasenameÚ
startswithr[   Ú	enumerater^   Úbr9   Út0r6   rX   rY   rK   rL   r_   r2   Úsum)r­   rp   s   00r=   Ú<module>r°      s©  ðñ÷ +× *× *Û Ø	‡w�w‡��r—w‘w—‘ xÓ0Ó1€Ø ‡�‡���4Ô Û Ý Û à‡C�C€ˆb�i‰i�m‰m˜AÓˆØ‡g�g‡l�l�4˜Ó&€°·±·±¸TÀ;Ó0O¨ôô"ò*	ôZð ˆzÔØ	×	 Ò	 Ó	"€B B§O¡O°JÀSÐRS OÑ$TÐVX×VeÑVeÐfoÐvyð  DFÐVeñ  WGØ‡O�O�H 3°€OÑ2°B·O±OÀIÐVb°OÑ4cÐik×ivÑivÓixÐefØ‡w‡w‘E“G�™U¡3 q£6Ð+DÔEÀsÇxÂxÄzÙ‹5€DØ	‡w�w‡~�~�c×ÑÙ�c–ˆAØ—‘˜$Ÿ*š* Q›-¨Ñ0Ö1ñ ñ �D—I’I˜bŸg™gŸl™l¨4°¸¸kÓJÓKÐQS×QXÑQX×QaÑQaÐkoÑp€FÙó  Rš�A 2§7¡7×#3Ñ#3°B·G±G·O±OÀAÓ4FÓ#GÈtÑ#S‹aÐ\^×\cÑ\c×\lÑ\lÐmo×mtÑmt×m|Ñm|Ð}~Ómó  ]A÷  ]Lñ  ]Lð  MP÷  ]Q�a™ñ  R€FØ‡x‡x˜&  !§(¡(Ð+�Ù	ˆc�3Œ˜3Ù˜f×%‰DˆAˆqØ—7‘7×#Ñ# B§G¡G§O¡O°AÓ$6Ó7ˆD¸d¿iºi»k¸Ù˜1 1Ñ%ˆAØ‰y™% Ð&8Ô9¹8Ù˜˜D !§'¡'¨1¯6©6°2·9±9×3HÑ3HÈÓ3KÈSÓQˆDÙ�T�F˜"™S §¡£›_Ð-¨Y±sÑ\`Ó;aÒ\`ÐWX¸v¹YÈÈ&É	Ó<RÑ\`Ñ;aÓ7bÐ6cÐckÙÑ/©$Ó/Ó/Ð0°±#°d³)°¸FÀ4Ç9Â9Ã;ÐQSÑCSÐTWÐBXÐXZð\Øcgõiñ &÷ 
ñ 
…Gð) øð Ó#›tÐ#üò Rùò <b÷ 
�úsE   Ç$PÈ7<P,É7AP,ËP,Ë3CP6Î9P1ÏAP6ÐP)Ð(P)Ð1P6Ð6
Q