
    eRji                       U d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZ ej                  j                  d e e
e      j#                         j$                               ddlmZmZmZ ddlmZmZmZ  e
e      j#                         j6                  d	   Zed
z  Zedz  Zedz  Zedz  Z edz  Z!g dg dg dg dgg dg dg dg dg dg dgg dg dg dgdZ"de#d<   d0dZ$d1d2d Z%d3d!Z&d4d"Z'd5d#Z(d6d$Z)d7d8d%Z*	 	 	 	 	 	 	 	 d9d&Z+	 	 	 	 	 	 	 	 	 	 d:d'Z,d6d(Z-d6d)Z.d;d*Z/d<d+Z0d=d,Z1d>d-Z2d?d.Z3e4d/k(  r e3        yy)@a  Build a focused EXE evidence review for map animation.

The map renderer has two different kinds of evidence that are easy to mix up:

* visual source-tile shift previews used in ``web/map_review.html``; and
* EXE-grounded dirty-redraw paths and generic palette VM candidates.

This report keeps them separated.  It also records a negative scan for simple
tile-id replacement tables so future work does not keep re-testing the same
assumption.
    )annotationsN)Counter)Path)Any)build_palette_binding_contextpalette_command_alignmentpalette_root_resource_binding)offset_to_varead_sectionsva_to_offset   zHwanse2.exeoutwebzmap_animation_tile_review.jsonz%map_palette_handler_trace_review.json)      )      )      )      )i  i  i  )i  i  i  )r   r   r   )r   r   r   )r   r   r   )r   r   r   ):   ;   <   )U   V   W   )i%  i&  i'  )zmap1_01a fire 4x3 row variantsz%map1_02b waterfall/water row variantsz(map1_02b bridge/static neighbor controlszdict[str, list[list[int]]]SUSPECTED_TILE_SEQUENCESc                V    t        j                  t        | 
|             S d            S )N )htmlescapestr)values    /tools/build_map_animation_exe_pattern_review.pyescr*   @   s&    ;;sE$55>??2>??    c                    | yd| d| dS )Nr$   0x0x )r(   widths     r)   hxr2   D   s"    }awaZ !!r+   c                p    | j                         s|S t        j                  | j                  d            S )Nutf-8encoding)existsjsonloads	read_text)pathfallbacks     r)   	load_jsonr=   J   s*    ;;=::dnngn677r+   c                t    |sg S g }d}	 | j                  ||      }|dk  r|S |j                  |       |dz   }0)Nr   r   )findappend)blobneedler   starthits        r)   all_occurrencesrE   P   sL    	CE
ii&7J

3a r+   c                    |dk(  rt        d | D              ry t        |       S |dk(  r+t        d | D              ry dj                  d | D              S |dk(  rdj                  d | D              S t        |      )	Nu8c              3  4   K   | ]  }|d k  xs |dkD    yw)r      Nr0   .0r(   s     r)   	<genexpr>z"encode_sequence.<locals>.<genexpr>_   s      :Uuqy(EDL(:   u16lec              3  4   K   | ]  }|d k  xs |dkD    yw)r   i  Nr0   rJ   s     r)   rL   z"encode_sequence.<locals>.<genexpr>c   s      <uuqy*EFN*<rM   r+   c              3  H   K   | ]  }t        j                  d |        yw)<HNstructpackrJ   s     r)   rL   z"encode_sequence.<locals>.<genexpr>e        BUD%0B    "u32lec              3  H   K   | ]  }t        j                  d |        yw)<INrR   rJ   s     r)   rL   z"encode_sequence.<locals>.<genexpr>g   rU   rV   )anybytesjoin
ValueError)seqr1   s     r)   encode_sequencer_   ]   sz    }:c::Sz<<<xxBcBBBxxBcBBB
U
r+   c                *   g }t               }t        j                         D ]  \  }}|D ]  }|j                  |       g }dD ]o  }t	        ||      }	|	t        | |	      }
|j                  ||	j                  d      t        |
      |
d d D cg c]  }t        t        ||             c}d       q |j                  ||dj                  d |D              |t        d |D              d         g }t        |      D ]  }t        j                  d	|      }	t        | |	      }
t!               }g }|
D ]y  }t        ||      }||j                  t        |             |D ]J  }t#        |d
         }|t#        |d         z   }||cxk  r|k  s.n 1|t%        |d         xx   dz  cc<    y { |j                  ||	j                  d      t        |
      t'        |      |d d d        ddd||t        |      t        d |D              dS c c}w )N)rG   rN   rW       )r6   bytePatternhitCounthitVasz -> c              3  2   K   | ]  }t        |        y wN)r'   rJ   s     r)   rL   z&scan_tile_sequences.<locals>.<genexpr>   s     /LuE
/L   c              3  &   K   | ]	  }|d      yw)rd   Nr0   rK   rows     r)   rL   z&scan_tile_sequences.<locals>.<genexpr>   s     2Xs3z?2Xs   )familysequencesequenceText	encodingstotalContiguousHitCountrQ   rawraw_sizenamer      )tilerN   rd   sectionCountsre   z2simple-contiguous-tile-replacement-table-not-foundzXknown fire/waterfall/waterfall-rope candidate tile-id triples and nearby static controlsznegative result only covers simple contiguous u8/u16/u32 encoded sequences, not compressed code, arithmetic generation, or palette-only animationc              3  2   K   | ]  }|d    dkD  sd  yw)rp   r   r   Nr0   rj   s     r)   rL   z&scan_tile_sequences.<locals>.<genexpr>   s      Ysc:S6TWX6X Y   )statusscope
limitationsequenceRowsindividualTileRowstotalSequenceRowscontiguousHitRows)setr"   itemsupdater_   rE   r@   hexlenr2   r
   r\   sumsortedrS   rT   r   intr'   dict)rA   sectionsrowsindividual_tilesrl   patternsr^   ro   r1   encodedhitsrD   individual_rowsru   section_countshit_vasvasectionrC   ends                       r)   scan_tile_sequencesr   k   sI   !#D!$4::<  	C##C(.0I1 )#u5?&tW5  $)'.{{3'7$'INRSVTVi"Xs2l8S&A#B"X	 KK$ #$*KK/L/L$L!*/22Xi2X/X!	6 O'( 
++dD)tW-'.y 		Ch,B~r"v&# GEN+c'*"566C%#%"3wv#78A=8			 	 S)I!%n!5!#2,	

4 Gk j- Y  Yd YY O #Ys   Hc                f  	 | t        d||z
        t        t        |       ||z          }g }t               }|D ]Z  }d|cxk  rdk  rn n|j	                  |       #t        |      dk\  r|j	                  t        |             |j                          \ t        |      dk\  r|j	                  t        |             g }|D ]#  }	 |j	                  |j                  d             % |D 		cg c]  	t        	fddD              r	 }
}	dj                  |
d d       S # t        $ r Y iw xY wc c}	w )	Nr       ~      asciic              3  B   K   | ]  }|j                         v   y wrg   )lower)rK   tokentexts     r)   rL   z%ascii_token_around.<locals>.<genexpr>   s     ou

$os   )z.cnsz.mlkz.wlkmap_btl_cara_middataz | )maxminr   	bytearrayr@   r[   cleardecodeUnicodeDecodeErrorrZ   r\   )rA   offsetradiussegmentrunscurrentbyte	text_runsrunr   interestings            ` r)   ascii_token_aroundr      s-   3q&6/*STFVO-LMGDkG 44NN4 7|q E'N+MMO 7|qE'N#I 	SZZ01 o2noo 	K 
 ::k"1o&& " 		s    D,D.	D+*D+c                   |j                  d      xs g }|D ch c]F  }|j                  dg       D ]/  }t        |j                  d      t              rt        |d         1 H }}}|D ch c]s  }|j                  dg       D ]\  }t        |j                  d      t              r;t        |j                  d      t              rt        |d         t        |d         f^ u }}}t        d |D        d      }t        d	 |D        d      }	t	        |      }
t        d
 |D              }t        |d         }t        t        |       dz
  |t        |d         z         }t               }d}g }g }g }g }t        ||      D ]  }| |   dk7  r| |dz      }|dvrt        j                  d| |dz         d   }t        j                  d| |dz         d   }t        j                  d| |dz         d   }|dk  xr ||k  xr ||	k  }||v }||f|v }|s|s|st        | |      }|j                  d      xs d}||xx   dz  cc<   |dv }|r|r|dz  }|j                  d      }t        ||
      } t        t        ||            ||dk(  rdnd|||| ||dz    j!                  d      |||j                  d      |j                  d      xs g dd | j                  d      | j                  d       | j                  d!g       dd" D !cg c]{  }!|!j                  d#      |!j                  d$      |!j                  d       |!j                  dg       dd |!j                  d%g       |!j                  d&g       |!j                  d'      d(} c}!| j                  d)g       dd" D !cg c]  }!|!j                  d#      |!j                  d$      |!j                  d       |!j                  d*      |!j                  dg       dd |!j                  d%g       |!j                  d&g       |!j                  d'      d+ c}!| j                  d,      d-d.}t#        | |      }"|"r(t        |      d/k  r|j%                  i ||"d0d1       |r'|s%t        |      d/k  r|j%                  i |d2d3i       |r#|r!|rt        |      d4k  r|j%                  |       |sK|rO|sS|sWt        |      d4k  sg|j                  d5      xs i j                  d      }#|"rd6}$n|#d7k(  rd8}$n|#r|#d9k7  rd:}$nd;}$|j%                  i ||$d<d=        d>d?d@ddAg dBdCdDdEdFdGdHg dIdJdDdKdLdGdMg dNdJdDgt        |      t        |      ||	t'        t)        |j+                                     |t        |      t        |      t-        dO |D              t-        dP |D              t        |      t        |      dQ||||g dRdSS c c}}w c c}}w c c}!w c c}!w )Ta  Scan opcode 0x58 tile-write command shapes against known 0x40 regions.

    Opcode 0x58 is grounded by disassembly as a real tile-grid write command,
    but a raw byte hit is not enough.  This scan keeps three things separate:

    * handler semantics, which are confirmed from code;
    * plausible aligned 0x58 command streams; and
    * whether any such command directly writes a known animated source tile id.
    mapsanimatedCellslayer0r/   yc              3  X   K   | ]"  }t        |j                  d       xs d       $ yw)r1   r   Nr   getrj   s     r)   rL   z+scan_tile_write_commands.<locals>.<genexpr>   s#     @CS).Q/@   (*r   )defaultc              3  X   K   | ]"  }t        |j                  d       xs d       $ yw)heightr   Nr   rj   s     r)   rL   z+scan_tile_write_commands.<locals>.<genexpr>   s#     Bcc#''(+0q1Br   c              3  2   K   | ]  }|d    dk(  s|  yw)rs   z.dataNr0   )rK   r   s     r)   rL   z+scan_tile_write_commands.<locals>.<genexpr>   s     VG76?g;UVrx   rq      rr   X   r   )r   r   rQ      r      i   ry   unknown>   vm-aligned-local-highvm-aligned-local-medium
bestRootVaz!write layer0 tile grid 0x00595af0z!write layer1 flag grid 0x0058d7d0ra   directReferenceCountpreviewN	rootVaHexcontainingGroups   idselectoranimatedMapsanimatedTilesets	linkClass)r   r   r   r   r   r   r   nearestGroupsdistanceBytes)r   r   r   r   r   r   r   r   note)ry   r   r   r   r   )r   modemodeMeaningru   r/   r   rq   alignmentStatusr   r   r   resourceBindingrt   zOcandidate overlaps asset/string bytes rather than an isolated VM command stream)asciiContextrejectedReasonr   zoknown animated tile id appears, but x/y is outside known map dimensions; treated as false-positive byte overlap   r   z-rejected-descriptor-or-resource-table-overlapz$resource-group-contains-animated-map4coordinate-correlation-inside-animated-resource-rootz
no-vm-rootz$rejected-nonanimated-or-unbound-rootzcoordinate-correlation-onlyzThe command touches a coordinate that is animated in at least one map, but writes a non-animated tile id. This is not visible animation proof unless the root also binds to the animated map.)classificationr   z6tile-write-handler-grounded-animation-binding-unproven0x58
0x00407686z!58 mode u16(tileId) u16(x) u16(y))zBmode 0 writes tileId to layer0 grid 0x00595af0 at y * mapWidth + xzGmode 1 writes tileId/flag to layer1 grid 0x0058d7d0 at y * mapWidth + xz?both modes call 0x004255eb(x, y) to invalidate the touched tilezconfirmed-handler)opcode	handlerVacommandByteslayout	semantics	promotion0x6b
0x00408d10rb   z96b mode actorFilter u16(xOffset) u16(yOffset) u16(tileId))z6iterates active descriptor slots 0x004576e8/0x0059dd70z!matches actor id or 0xff wildcardBwrites tileId at active-object base coordinate plus signed offsetsz!confirmed-handler-object-relative0x76
0x00409f23z976 mode actorFilter u16(xOffset) u16(yOffset) u16(tileId))z7iterates linked active object list rooted at 0x00574100z8matches actor id, 0xfe current context, or 0xff wildcardr   c              3  H   K   | ]  }|j                  d       dk(  rd  yw)r   r   r   N)r   rj   s     r)   rL   z+scan_tile_write_commands.<locals>.<genexpr>  s+      977+,0ff 9rV   c              3  t   K   | ]0  }t        |j                  d d            j                  d      rd 2 yw)r   r$   z	rejected-r   N)r'   r   
startswithrj   s     r)   rL   z+scan_tile_write_commands.<locals>.<genexpr>  s7      /sww/45@@M /s   68)animatedTileIdCountanimatedCoordinatePairCountmaxAnimatedMapWidthmaxAnimatedMapHeightcandidateAlignmentCountsplausibleAlignedOpcode58CountdirectAnimatedTileWriteCountcoordinateOnlyAlignedHitCount%coordinateOnlyInsideAnimatedRootCountcoordinateOnlyRejectedCount'rawAnimatedTileFalsePositiveSampleCountasciiFalsePositiveSampleCount)z^Tile-grid mutation opcodes are real and their layouts are now separated from palette evidence.zNo aligned, plausible opcode 0x58 command was found that directly writes one of the current known 0x40 animated layer0 tile ids.zSome aligned tile writes touch coordinates that are animated in a known map, but the known hits either write ordinary tile ids from nonanimated/unbound roots or overlap resource/descriptor tables.zObject-relative tile write opcodes 0x6b/0x76 may matter for doors/NPC/event map edits, but they do not currently bind the fire/waterfall loop.)ry   handlerssummarydirectAnimatedTileWritescoordinateOnlyAlignedHits#rawAnimatedTileFalsePositiveSamplesasciiFalsePositiveSamples
conclusion)r   
isinstancer   r   r   nextr   r   r   rangerS   unpack_fromr   r	   r2   r
   r   r   r@   r   r   r   r   )%rA   r   animation_reviewr   rk   cellanimated_tilesanimated_coord_pairs	max_width
max_heightbinding_contextdata_section
data_startdata_endalignment_countsplausible_aligneddirect_animated_writescoordinate_only_hitsraw_animated_tile_hitsascii_false_hitsr   r   ru   r/   r   	plausibletile_hit	coord_hit	alignmentry   aligned	best_rootbindinggroupascii_contextbinding_statusr   s%                                        r)   scan_tile_write_commandsr     s    '-2D GGOR0 dhhx(#. 	DNN  GGOR0 dhhsmS)j#.L 
T#YT#Y((  @4@!LIBTBANJ3D9OVxVVL\%()J3t9q=*s<
3K/L"LMH%,Y351335-/
H- g<4FQJv!!$fqj9!<tT6A:6q9tT6A:6q94KDA	MDa*n	>)F22	X-dF;	x(5I A% PP"MM,/	/	?K\(F34BF!)>Qt!,005%#$-MM2H$I!i06B;!++h/$[[5 ")-?!DRa!H%  $iio$)IIj$9%*YY{%; %		&" 5bq 9(-		."(E,1II6H",M%*YY{%;%. ")_b!A"1!E"  $iio$)IIj$9%*YY{%;).?)C %		&" 5bq 9(-		."(E,1II6H",M%*YY{%;	"  F+9 *
V +48#$r) ''(5*{ I#.D*E*J"))$  'X 	g#6L2MPR2R"))#.X)CH\D]`bDb!gg&78>BCCHMN!P#II!WNl$B!G!> ''&4 \CgT K !) !=
 1 !) "U
 A !) "U
 A3%
N $'~#6+./C+D#,$.(,V4D4J4J4L-M(N->,/0F,G-01E-F58 9/9 6
 ,/ /// ,
 8;;Q7R-01A-B)
, %;%9/E%5
EH HIx%"s   AW0.A8W6B W< BX"c           	        t        ||      }|g S g }t        |      D ]k  }||dz  z   }|dz   t        |       kD  r |S t        j                  d| |      \  }}	}
}|j                  |t        ||dz  z         ||	|
|g|
|z
  ||	z
  gd       m |S )Nrt   z<4i)indexr   rectsize)r   r  r   rS   r  r@   r2   )rA   r   base_vacountr   r   r!  item_offsetlefttoprightbottoms               r)   read_rect_tabler+    s     (G,F~	Du 
urz)c$i' K $*#5#5eT;#O c5&52:-.sE62v|4		

 Kr+   c                ^    d3d4 fd} |dddh      } |dddh      }dd	d
ddddddddddgddt         dd      dddt         dd      dddt         dd      dg||ddd d!d"gg d#g d$g d%g d&g d'g d(g d)g d*g d+g d,g d-g
d.d/t        |      t        |      d0g d1d2S )5aT  Record the self-blit command path separately from tile-id mutation.

    Runtime traces already prove that map_a updates a live cache area through
    surface self-blits.  Static evidence shows the generic helper that performs
    those self-blits, but map_c's beach rows have not been tied to the same
    executed command family yet.
    c                8   t        |       }t        |      }||g S g }t        |t        |t              dz
              D ]  }|   }||vs|dz      dk7  rt	        j
                  d|dz         d   }	t	        j
                  d|dz         d   }
t	        j
                  d|d	z         d   }|j                  t        t        |            t        |d      d
|	|
t        |      ||dz    j                  d      d       t        |      |k\  s |S  |S )Nrb   r   r   rQ   r   r   r   rY   r   0x02ra   )r   r   submodeword4word6	ptrOrArg8rq   )
r   r  r   r   rS   r  r@   r2   r
   r   )start_vaend_vaopcodeslimitrC   r   r   r   r   r0  r1  ptr8rA   r   s               r)   sample_commandsz6scan_rect_copy_command_family.<locals>.sample_commands  s=   Xx08V,=CKIE3sCIN#;< 	F&\FW$VaZ(8D(@&&tT6A:>qAE&&tT6A:>qAE%%dD&1*=a@DKK\(F;< m%""!#D"599#>
 4yE!)	( r+   i*D i,D ]   iE iF e   z7self-blit-helper-grounded-map-c-beach-runtime-confirmed
0x004256D1zsurface self-blit helperzkcalls BltFast wrapper twice, surface 0x0a -> 0x0a and surface 0x0b -> 0x0b, using rectBase + wordIndex * 16)r   roleevidence
0x0040791Fz%stream consumer into self-blit helperzreads current stream pointer from context+0x40, rect table base from context+0xa8, then forwards two stream words into 0x004256D1
0x00417750zDirectDraw Blt/BltFast wrapperzBfinal DirectDraw surface copy wrapper used by the self-blit helper
0x00442761z'map_a 64x48 cache block + source framesia'D r   )baseVar<  rects
0x004427A1z.map_b/map_a strip-style cache source candidatei'D 
0x004427B1zstrip cache rect continuationi'D zMcaptures/runtime/hwanse-runtime-trace-2026-07-11T15-18-27-318Z-ani-wave.jsonl
0x004177DA
0x00419BC7z
map_c1.cnsz
map_c2.cns)iP     i     )r   rG  0   rH  )rI  rG  `   rH  )rJ  rG     rH  )rK  rG  rH  rH  )rH  rG     rH  )rL  rG     rH  )rM  rG  P  rH  )rN  rG    rH  )rO  rG    rH  )rP  rG  i  rH  z1every 4 runtime frames, roughly 200ms in ani-wave)traceselfBlitCallerscreenConsumerCallersurfacescacheDestRectsourceFrameRectsobservedCadence)mapACommandSampleCountmapCRootCandidateCount)zThe self-blit/cache mechanism is real and is strong evidence for map_a/map_b style animation when paired with runtime surface traces.zani-wave runtime binds map_c beach motion to the same cache-consumer model: map_c1/map_c2 self-blit 48x32 source frames into cache 592,160..640,192, then 0x00419BC7 draws those cache cells.zThe older map_c 0x65/0x02 local-root rows remain unpromoted and should not be used as the animation model now that the runtime cache path is known.)ry   confirmedHelperPathmapARectTablesmapACommandSamplesmapCRootCommandCandidatesmapCRuntimeTraceEvidencer   r   )r   )
r3  r   r4  r   r5  zset[int]r6  r   returnlist[dict[str, Any]])r+  r   )rA   r   r8  map_a_samplesmap_c_sampless   ``   r)   scan_rect_copy_command_familyrc    s1   8 $J
TFCM#J
TFCMK #2 J #? ` #8` 
& 'A(xQG 'H(xQG '7(xQG
" ,%2d*$0%|41!"#$$$$$$$!  S%%
* '*-&8&)-&8

}C Cr+   c                L   dj                  d t        d      D              }g }t        | |      D ]Y  }t        ||      }|t	        d|dz
        }| ||t        |      z   dz    }t        t        j                  dd	t        |      d
z  z  z   |dt        |      d
z  d
z               }g }	t        dt	        dt        |      dz
              D ]P  }
||
   dk(  s||
d
z      dk(  s||
dz      }||
dz      }|dk  s.|dk  s4|	j                  ||d|dd|dd       R |j                  t        |      | ||t        |      z    j                  d      g dd|	t        t        ||            |dd D cg c]  }d|d
 c}d       \ t        | |dd      }ddddddd d!d"d#ddd$d g}|D cg c]C  }|j                  d%g       D ],  }|j                  d&      d'k(  r|j                  d(      dk(  r|. E }}}d)dd!d*|||d'dd+d,t        |      d-d.g d/d0	S c c}w c c}}w )1a  Record the map_c3 whirlpool source-rect and frame-loop evidence.

    This is intentionally separate from layer1 0x40 tile animation.  map_c3 is
    loaded as an extra tileset/object resource and has its own 4-frame source
    rect table.  The map-space placement still needs a direct draw consumer
    trace, so the review labels the position as a candidate rather than a final
    promotion.
    r+   c              3  N   K   | ]  }t        j                  d dd|d        yw)z<HHHH!   r   rb   NrR   )rK   r!  s     r)   rL   z(scan_map_c3_whirlpool.<locals>.<genexpr>9  s!     [&++gtQtD[s   #%r   Nr   rJ  @   <Hr   r   i  i  r      zword-pairs e802 04xz, ea02 )r/   r   r=  ra   )r   r   r   r   0x000crI  r-   )r   rq   framesslotHexnearbyPlacementCandidates	contextVacontextWordsilR map2_13c
0x00531fc4
0x00531fecz
map_c3.cnsz6resource-ref-only; candidate x=53 exceeds map width 37)maprecordVaresourceRefVarn  stringplacementStatusmap6_26c
0x0053207c
0x005320a4zBsource-rect-and-frame-loop-confirmed; placement candidate x=53,y=4ro  r/   5   r   zCsource-rect-table-and-slot-frame-loop-confirmed-placement-candidate
0x0052df6c
   r   zMnearby-active-object-position-word-pairs; direct draw consumer still unproven)r/   r   whrd   evidenceStatus)zamap_c3.cns is a four-frame 160x128 whirlpool sheet, grounded by EXE source rect table 0x0052df6c.z_The slot 0x0c frame loop 0,1,2,3 appears exactly twice in the EXE at 0x005314f0 and 0x00531bc8.zBoth loop contexts carry nearby e802/ea02 word pairs with x=53,y=4, which is plausible for map6_26c and out of bounds for map2_13c; map_review therefore renders map6_26c at tile 53,4 as a placement candidate.zThe final unresolved item is a direct map-space draw consumer/runtime trace tying those word pairs to the visible object position.)	ry   assetru  sourceRectTableVasourceRectsframeLoopHitsresourceRefscandidatePlacementr   )r\   r  rE   r
   r   r   listrS   unpackr@   r2   r   r+  r   )rA   r   
frame_loopr   r   r   context_startcontextcontext_wordsplacement_candidatesr!  r/   r   wordsource_rectsresource_refsrD   	candidatecandidate_positionss                      r)   scan_map_c3_whirlpoolr  /  s    [RWXYRZ[[JD!$
3 "
(F+:Av{+}vJ'?"'DEV]]3G8I1J+JGTmWZ[bWcghWhlmVmLnop!1c!S%7!%;<= 	E
 U#v--	2Jf2T!%!),!%!),s7q3w(//!"!"*:1S'3(P	  	fFVc*o%=>BB3G&#-AX} EF=J3B=O PT2d3Z P
	
1"
H #4:qAL $)"W	
 $)"c	
M( !<bA ==#	c(:a(? 	  X)#%/0m

! ; !Q.s   4H2AH c                n   | j                  d      xs i j                  d      xs g }g }|D ]z  }|j                  d      xs i }|j                  d      xs g }|j                  d      xsB |j                  dg       D cg c]&  }|j                  d      s|j                  d      r|( c}}t        j                  |||gd	
      }d|vrd|vr|j                  |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      xs i j                  d      |j                  d      xs i j                  d      |j                  d      xs i j                  d      |j                  d      xs i j                  dg       d d |j                  d      xs i j                  d      d|j                  d      |j                  d      |d d |d d D 	cg c]j  }	|	j                  d      |	j                  d      |	j                  d      |	j                  d       |	j                  d!g       d d |	j                  d"g       d#l c}	d$d%	       } |S c c}w c c}	w )&NpaletteCommandScancommandsr   r   nearestAnimatedSceneRecordsnearestSceneRecordsanimatedMapr   F)ensure_asciimap1_01amap1_02br   r   r   kindr  effectScope
payloadHexscriptAlignmentry   r   r   r   r   r   )ry   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   )ry   r   r  r   )	r   r   r   r  r  r  r  r  r   )r   r8   dumpsr@   )
r  r  pickedrk   r  nearestrecordnearest_recordsr   r  s
             r)   pick_map1_palette_candidatesr    s   !%%&:;ArFFzRXVXHF ,
''+,2++o.4"!++&CD 
!++&;R@I
zz-(FJJ7I,J I

 zz7G_=ERT!j&<ggdm''(+)"ww}5!ggl3"ww'89?RDDXN#&77+<#=#C"H"H"V-0WW5F-G-M2,R,RSi,j #(9 : @bEEiQSTUWVWX WW%67=2BB6J$ &kk(3!([!93B2A3F &-Ra[
& " #())D/(-		*(=).;)?-2YY-G$)IIfb$9"1$=,1IInb,I
&	$!	
,
Z MUI
8
&s   +J-.A/J2 c                    t         j                         } t        |       }t        t        i       }t        t
        i       }t        | |      }t        | ||      }t        | |      }t        | |      }|j                  d      xs i }|j                  d      xs i }	|j                  d      xs i }
t        |      }ddddddd	d
dddi d|	j                  d      d|	j                  d      d|	j                  d      d|d   d|d   dt        |      d|	j                  d      d|	j                  d      d|
j                  d      d|
j                  d      d|
j                  d      d|d   d   d|d   d   d|d   d    d!|d   d"   d#|d   d$   d%|d   d&   |d   d'   t        |d(         d)t        t        j                  t                    |j                  d*      |j                  d      |j                  d+g       |j                  d,g       |j                  d-i       d.t        t
        j                  t                    |
|j                  d+g       |j                  d,g       d/|||||d0d1d2d3d4d5S )6NexeEvidencer   r   z'hwanse-map-animation-exe-pattern-reviewz2animation-redraw-and-cache-visible-motion-groundedzCurrent EXE/runtime evidence grounds layer1 0x40 dirty redraw and cache self-blit visible motion for the known fire/waterfall/beach animated regions.zjNo simple contiguous tile-id replacement table was found for the known fire/waterfall candidate sequences.zpThe layer1 0x40 consumer marks viewport cells dirty and does not choose alternate layer0 tile ids at that point.zvPalette opcodes 0x38/0x39 are table-dispatched VM commands and eventually apply through DirectDrawPalette::SetEntries.zMost palette candidates that are near animated scene records touch broad palette ranges, so they are better treated as screen fade/transition evidence than localized fire/waterfall loop proof.zOpcode 0x58/0x6b/0x76 tile-grid mutation handlers are real, but they do not yet bind to the 0x40 fire/waterfall visible motion loop.zThe known visible map animation previews now use cache/self-blit evidence where available. Palette VM and tile-write handlers remain useful secondary paths, but they are not the primary visible-motion model for these regions.)shorttileReplacementdirtyRedraw	paletteVmpaletteCandidateScopetileWriteVmremainingGapanimatedMapCountanimatedCellCountanimatedPaletteIndexRangestileSequenceRowsScannedr~   "tileSequenceRowsWithContiguousHitsr   map1PaletteCandidateCountpaletteCommandEffectScopeCounts.paletteCommandNearAnimatedBroadTransitionCountpaletteHandlersTableOnlyexactPerMapPaletteRootProven mapAnimationPaletteBindingStatus&tileWritePlausibleAlignedOpcode58Countr   %tileWriteDirectAnimatedTileWriteCountr   &tileWriteCoordinateOnlyAlignedHitCountr   .tileWriteCoordinateOnlyInsideAnimatedRootCountr   $tileWriteCoordinateOnlyRejectedCountr   selfBlitMapACommandSampleCountrX  rY  r  )selfBlitMapCRootCandidateCountmapC3WhirlpoolFrameLoopHitCountry   	confirmed
unresolvedkeyAddresses)sourcery   r   r  r  r  )r  r   r  r  z*web/map_review.html MAP_ANIMATION_PREVIEWSz#visual approximation / audit helperzruntime tile-id replacementa  It lets a human compare promoted visible fire/waterfall/beach motion while keeping palette/tile-write candidates separate. map_c beach preview is now runtime-confirmed from ani-wave self-blit/cache evidence rather than the older unpromoted row-pair or pixel-scroll review candidates.)r  meaning
notProofOfwhyStillUseful)versionr  promotionStatusr   r   exeEvidenceCarryOverpaletteHandlerCarryOvertileReplacementScantileWriteCommandScansurfaceSelfBlitCommandScanmapC3WhirlpoolObjectAnimationmap1PaletteCandidatesmapReviewPreviewMeaning)EXE
read_bytesr   r=   MAP_ANIMATION_REVIEWPALETTE_TRACE_REVIEWr   r  rc  r  r   r  r   r'   relative_toROOT)rA   r   r  palette_trace	tile_scantile_write_scanrect_copy_scanmap_c3_whirlpoolexe_evidencer   trace_summarymap1_candidatess               r)   
build_datar    s`   >>DT"H !5r:2B7M#D(3I.tX?OPO24BN,T8<#''6<"L""9-3G!%%i06BM23CDO 9O m  L N R &h b @

,> ?
-@!A
 )'++6R*S
 &y1D'E	

 1)<O2P
 (_)=
 .w{{;\/]
 =gkkJz>{
 '(9(9:T(U
 +M,=,=>\,]
 /0A0ABd0e
 5oi6PQp6q
 4_Y5OPn5o
 5oi6PQp6q
 =oi>X  ZA  ?B
  3OI4NOl4m!
" -nY.GH`.a#
$ /=Y.GH`.a/23CO3T/U'
, .::4@A"&&x0#''	2%))+r:&**<<(,,^R@!
 .::4@A$&**;;'++L"=	$
  ) /&4)9!0B<7 |	$
k; ;r+   c                    g }|D ]/  }|j                  ddj                  d |D              z   dz          1 ddj                  d | D              z   dz   dj                  |      z   d	z   S )
Nz<tr>r$   c              3  (   K   | ]
  }d | d  yw)z<td>z</td>Nr0   )rK   r  s     r)   rL   zrender_table.<locals>.<genexpr>  s     $HDtD6%7$Hs   z</tr>z<table><thead><tr>c              3  :   K   | ]  }d t        |       d  yw)z<th>z</th>Nr*   )rK   headers     r)   rL   zrender_table.<locals>.<genexpr>  s     BDVU+B   z</tr></thead><tbody>
z</tbody></table>)r@   r\   )headersr   bodyrk   s       r)   render_tabler    s    D TFRWW$HC$HHH7RST 	
''B'B
B	C
 	! ))D/	 		r+   c                   | d   }| d   }| d   }|d   D cg c]k  }dt        |d          ddt        |d          dt        |d	         dt        |d
          ddj                  d |d   D              t        |d         gm }}|j                  dg       D cg c].  }dt        |d          dt        |d         t        |d         t        |d          dt        |d          t        |d         dt        |j                  d             ddt        |j                  d             dt        |j                  d      xs i j                  d             ddj                  d |j                  d      xs i j                  d      xs g D              xs d dj                  d! |j                  d"g       d d# D              g	1 }}|j                  d$g       D cg c]f  }dt        |d          dt        |d         t        |d          dt        |d          t        |d         t        |j                  d%            gh }}|j                  d&g       D cg c]  }dt        |d          dt        |d          d't        |d          dt        |d          t        |d         t        |j                  d(            t        |j                  d%            g }}|j                  d)g       D cg c]S  }dt        |j                  d             dt        |j                  d*            t        |j                  d+            gU }	}g }
|j                  d,g       D ]  }|j                  d-g       D ]  }|
j                  dt        |j                  d.             dt        |j                  d*            t        |j                  d/            dt        |j                  d             dt        |j                  d0            t        |j                  d1            g         |j                  d2g       D cg c]  }dt        |j                  d             ddt        |j                  d             dt        |j                  d3            t        |j                  d4            dt        |j                  d5             ddt        |j                  d6             dg }}|j                  d7g       D cg c]  }dt        |j                  d             ddt        |j                  d             dt        |j                  d3            t        |j                  d4            dt        |j                  d5             ddt        |j                  d6             dg }}|j                  d8g       D cg c]l  }t        |j                  d/            dt        |j                  d             dt        |j                  d0            t        |j                  d1            gn }}|j                  d9g       D cg c]  }dt        |j                  d             dt        |j                  d:            t        |j                  d;            dj                  d< |j                  d=g       D              xs d dt        |j                  d6             dg }}|j                  d>g       D cg c]  }t        |j                  d?            dt        |j                  d@             ddt        |j                  dA             dt        |j                  d:            t        |j                  dB            g }}g }| dC   dD   D ]M  }dj                  dE |dF   D              }|j                  t        |dG         dt        |dH          d|g       O g }| dC   dI   D ][  }|j                  dt        |d          dt        |dJ         t        |dK         dLj                  dM |dN   d dO D              g       ] g }| dP   D ]d  }|dQ   }|d   }|j                  dR      xs g }dj                  dS |D              }|j                  dt        |j                  d             dt        |j                  d             dTt        |j                  d             t        |j                  dU            t        |j                  dV      xs i j                  dW             dXt        |j                  dV      xs i j                  dY             dt        |j                  d             dZt        |j                  d             t        |j                  d            |g       g | d[   }| d\   }d]j                  g d^t        |d_          d`t        |da          dbt        |j                  dc             ddt        |j                  de             dft        |j                  dg             dht        |j                  di             djt        |j                  dk             dlt        |j                  dm             dnt        |j                  do             dpt        |j                  dq             drt        |j                  ds             dtt        |j                  du             dvt        |j                  dw             dxt        |j                  dy             dzt        |d{          dLt        |d|          dLt        |d}          d~t        |d          dt        |da          dt        | d   d          dt        | d   d          dt	        g d|       dt	        g d|       dt        |d\          dd]j                  d |d[   D               dt	        g d|       dt	        g d|xs g dg       dt	        g d|xs g dg       dt	        g d|xs g dg       dt        |j                  d             dd]j                  d |j                  d[g       D               dt	        g d|	       dt	        g d|
xs g dg       dt	        g d|xs g dg       dt	        g d|xs g dg       dt        |j                  d             dt        |j                  d             dd]j                  d |j                  d[g       D               dt	        g d|xs g dg       dt	        g d|xs g dg       dt	        g d|xs g dg       dt	        g d|       dt        t        j                  | d   dd             d      }|S c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w )Nr  r  r  r   <code>r   </code>r   r   r   z<br>c              3  2   K   | ]  }t        |        y wrg   r  rK   items     r)   rL   zrender_html.<locals>.<genexpr>(  s     ?dD	?rh   r   r   r   r   r   ru   r/   ,r   r   r   z<span>r   z</span><br><span class='muted'>r   ry   </span>c              3     K   | ]g  }t        |j                  d              dt        |j                  d             ddj                  d |j                  dg       dd D                i yw)r   ra   r   c              3  2   K   | ]  }t        |        y wrg   r  )rK   map_names     r)   rL   z(render_html.<locals>.<genexpr>.<genexpr>9  s     ThCMTrh   r   Nr   )r*   r   r\   )rK   r  s     r)   rL   zrender_html.<locals>.<genexpr>7  sp        uyy'(#eii
.C*D)EQ88T%))FB:OPRQR:STTUWs   A-A/r   z<span class='muted'>-</span>c              3  2   K   | ]  }t        |        y wrg   r  r  s     r)   rL   zrender_html.<locals>.<genexpr>=  s     IdD	Irh   r      r   r   r   z @ r   rZ  r<  r=  r[  rB  rA  r!  r"  r#  r\  r0  r1  r2  rq   r]  r  r  rn  rm  c           
   3     K   | ]W  }t        |j                  d              dt        |j                  d             dt        |j                  d             d Y yw)r/   r  r   z <span class='muted'>r=  r  Nr*   r   r  s     r)   rL   zrender_html.<locals>.<genexpr>  s]       txx}%&aDHHSM(:';;PQTUYU]U]^hUiQjPkkrss   AAro  r  ru  rv  rw  ry  r  r|   c              3  Z   K   | ]#  }t        |d           dt        |d           % yw)r6   z: rd   Nr  r  s     r)   rL   zrender_html.<locals>.<genexpr>  s9      
 4
#$%RD,<(='>?
s   )+ro   rl   rn   r}   rd   rv   ra   c              3  :   K   | ]  }d t        |       d  yw)r  r  Nr  )rK   r   s     r)   rL   zrender_html.<locals>.<genexpr>  s     Or6#b''2Or  re   r   r  r  r  c           
   3     K   | ]V  }t        |j                  d              dt        |j                  d             dt        |j                  d              X yw)ru  z <code>recordVaHexz</code> dist=r   Nr  r  s     r)   rL   zrender_html.<locals>.<genexpr>  sZ      #
 488E?#$GC0G,H+IWZ[_[c[cds[tWuVvw#
s   AAz/mr  r  startHexz..endHexz</code><br>r   r   r$   u  <!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Map Animation EXE Pattern Review</title>
  <style>
    :root { color-scheme: light dark; --line:#d8dee8; --muted:#64748b; --panel:#f8fafc; }
    body { margin:0; padding:24px; font-family: system-ui, -apple-system, Segoe UI, sans-serif; line-height:1.45; }
    h1 { margin:0 0 12px; font-size:24px; }
    h2 { margin:28px 0 10px; font-size:18px; }
    code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
    .summary { display:grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap:10px; margin:16px 0; }
    .card { border:1px solid var(--line); border-radius:8px; padding:12px; background:var(--panel); }
    .card strong { display:block; font-size:18px; }
    .callout { border-left:4px solid #2563eb; padding:10px 12px; background:color-mix(in oklab, #2563eb 8%, transparent); }
    .warn { border-left-color:#d97706; background:color-mix(in oklab, #d97706 10%, transparent); }
    table { width:100%; border-collapse:collapse; font-size:13px; margin:10px 0 20px; }
    th, td { border:1px solid var(--line); padding:7px 8px; vertical-align:top; }
    th { text-align:left; background:rgba(148,163,184,.16); }
    .muted { color:var(--muted); }
    @media (prefers-color-scheme: dark) {
      :root { --line:#334155; --muted:#94a3b8; --panel:#111827; }
      body { background:#020617; color:#e5e7eb; }
    }
  </style>
</head>
<body>
  <h1>Map Animation EXE Pattern Review</h1>
  <p class="muted">타일 교체/offset 가설과 EXE animation dirty redraw 근거를 분리한 요약이다.</p>
  <div class="callout">
    <strong>결론:</strong> r  z	
    <br>r  z@
  </div>
  <div class="summary">
    <div class="card"><strong>r  zM</strong><span>0x40 animated maps</span></div>
    <div class="card"><strong>r  zE</strong><span>0x40 cells</span></div>
    <div class="card"><strong>r  /r  zY</strong><span>tile replacement sequence hits</span></div>
    <div class="card"><strong>r  zW</strong><span>map1-near palette candidates</span></div>
    <div class="card"><strong>r  zV</strong><span>direct animated tile writes</span></div>
    <div class="card"><strong>r  zZ</strong><span>coordinate-only tile-write hits</span></div>
    <div class="card"><strong>r  z\</strong><span>coordinate hits in animated roots</span></div>
    <div class="card"><strong>r  zS</strong><span>coordinate hits rejected</span></div>
    <div class="card"><strong>r  zZ</strong><span>map_a self-blit command samples</span></div>
    <div class="card"><strong>r  zV</strong><span>map_c unpromoted candidates</span></div>
    <div class="card"><strong>r  u   </strong><span>map_c3 whirlpool frame loops</span></div>
  </div>

  <h2>승격/미승격</h2>
  <div class="callout">
    <p><strong>확정:</strong> r  r  r  u,   </p>
    <p><strong>부정 증거:</strong> r  uN   </p>
  </div>
  <div class="callout warn">
    <p><strong>미확정:</strong> u=   </p>
    <p><strong>map_review 미리보기 의미:</strong> r  r  z. r  uT   의 증거로 쓰지 않는다.</p>
  </div>

  <h2>Known Tile Sequence Scan</h2>
  )rl   rm   zcontiguous hits by encodingu   

  <h2>Individual Tile ID Occurrences</h2>
  <p class="muted">개별 u16 값은 EXE 안에 흩어져 있지만, 순차 치환 테이블 형태로는 잡히지 않는다.</p>
  )ru   zu16 hit countr   z
sample VAsu  

  <h2>Tile-Write VM Command Scan</h2>
  <p class="muted">tile-grid write handler 자체는 확정이지만, 현재 known 0x40 source tile id를 직접 써서 모닥불/폭포를 재생한다는 증거는 없다.</p>
  <div class="callout">
    <p><strong>summary:</strong> z</p>
    <ul>c              3  :   K   | ]  }d t        |       d  ywz<li>z</li>Nr  r  s     r)   rL   zrender_html.<locals>.<genexpr>  s     NT4D	{%(Nr  z</ul>
  </div>
  )r   handlerr[   r   r   r   u   
  <h3>Coordinate-only aligned hits</h3>
  <p class="muted">좌표만 0x40 영역과 겹치는 경우다. tile id가 animated source tile이 아니므로 animation proof로 승격하지 않는다.</p>
  )	VAr   ru   x,yr  	best rootr   zcontaining root groupr   )	r$   r$   r$   r$   r$   r$   r$   r$   noneu   
  <h3>Rejected raw animated tile hits</h3>
  <p class="muted">known animated tile id처럼 보이나 좌표가 맵 범위를 벗어난 raw byte overlap 샘플이다.</p>
  )r  ru   r	  r  reason)r$   r$   r$   r$   r  u   
  <h3>Rejected ASCII/resource overlaps</h3>
  <p class="muted">리소스 문자열 주변에 걸린 0x58 byte는 command로 승격하지 않는다.</p>
  )r  z
tile @ x,yr  zascii contextr  uE  

  <h2>Surface Self-Blit / Cache Command Scan</h2>
  <p class="muted">0x40 dirty redraw가 아니라, 실제 CNS surface 내부 cache를 갱신하는 경로다. map_a/map_b에는 강한 근거가 있으나 map_c 해변은 아직 이 경로에 묶이지 않았다.</p>
  <div class="callout">
    <p><strong>status:</strong> c              3  :   K   | ]  }d t        |       d  ywr  r  r  s     r)   rL   zrender_html.<locals>.<genexpr>(  s     UT4D	{%(Ur  )r  r<  r=  z(
  <h3>map_a / map_b rect tables</h3>
  )baser<  r!  rect VAr"  r#  )r$   r$   r$   r$   r$   r  z2
  <h3>map_a promoted-like command samples</h3>
  )r  r   r0  r1  zptr/arg8rq   u   
  <h3>map_c root candidates, not promoted</h3>
  <p class="muted">map_c root의 0x65/0x02 행들은 trailing 값이 local pointer처럼 보이며, 아직 0x004256D1 self-blit helper 소비자로 연결되지 않았다.</p>
  u   

  <h2>map6_26c / map_c3 Whirlpool Object Animation</h2>
  <p class="muted">이 섹션은 layer1 0x40 타일 strip이 아니라, map_c3.cns extra-object 프레임 루프 근거다.</p>
  <div class="callout">
    <p><strong>status:</strong> z2</p>
    <p><strong>candidate placement:</strong> r  c              3  :   K   | ]  }d t        |       d  ywr  r  r  s     r)   rL   zrender_html.<locals>.<genexpr>8  s     RT4D	{%(Rr  z9</ul>
  </div>
  <h3>source rect table 0x0052df6c</h3>
  )r!  r  r"  r#  )r$   r$   r$   r  z(
  <h3>slot 0x0c frame loop hits</h3>
  )r  slotrm  znearby x,y candidatesrq   z
  <h3>resource refs</h3>
  )ru  r  zresource refr  zplacement statusu   

  <h2>map1 Palette Candidates</h2>
  <p class="muted">후보 command stream shape는 맞지만 map root 실행 연결은 아직 증명되지 않았다.</p>
  )r  r   r  r  r
  r  znearest animated scene recordsz)

  <h2>Carried EXE Evidence</h2>
  <pre>r  Fr   )r  indentz</pre>
</body>
</html>
)r*   r\   r   r@   r  r8   r  )data
tile_write	rect_copymap_c3rk   tile_write_handler_rowstile_write_coord_rowstile_write_false_rowstile_write_ascii_false_rowsrect_copy_helper_rowsrect_copy_rect_rowstabler"  rect_copy_map_a_rowsrect_copy_map_c_rowsmap_c3_rect_rowsmap_c3_loop_rowsmap_c3_resource_rowssequence_rowsencr   candidate_rowsscriptr  r  nearest_textr   r   docs                                r)   render_htmlr)    s}   ,-J12I12F j)
  SX'(0S[)*+73N#$SX'(0KK?c+.>??K !	

 
: >>"=rB%$ ! ST^$G,FF3s8}oQs3s8}o.%&'S./08S!1234 5##&0A(B(Hb'M'Mh'W#X"YY`bKK   #ww'89?RDDEWX^\^  .
 .KKIcggi.DRa.HII	
 8 >>"GL	  ST^$G,F3s8}oQs3s8}o.%&'()*	
	 	$ >>"=rB	#  ST^$G,3v; CCM?!CCM?C%&''(()*	
	# 	#  ==!6; 	 S'(0 
#$	
  /4 IIgr* 
	D&&S8!456g>		&)*)*S$019()()	
	* ==!5r:
  S'(0S*+,G4 ! !S-./w7S()1	

 
( ==!<bA
  S'(0S*+,G4 ! !S-./w7S()1	

 
$ JJ}b1  !"S$()1 ! !		
 * ::or2  S'(0	"#!"KK GG$?D  . .S()1
	
 , ::nb1	  S,-.g6S1237;	"#)*+	
	 	 M)*>: 
kk 
K(
 
 	CM"S012':	

 O)*+?@ 
S[)*'2C
O$C()OS]2A=NOO		

 N+, 
&''(++;<B{{ #
#
 
 	SWWT]+,G4swwx()*"S-A,BCCGGFO$(.B33J?@ACQXIYI_]_HdHdemHnDoCpqVZZ567{3vzzRZG[C\B]^GKK)*
	

( l#J9oGw w  w> "*W"567?w>8	?w@ 
Z'	()Aw@*AwF  #7;;/A#BCDGwFEGwH  #7;;/B#CDEIwHFIwJ  #7;;/S#TUVKwJ WXKwJ Y\\c\g\g  iB  ]C  YD  XEKwJEKwL  #7;;/J#KLMMwLNMwN  #7;;/V#WXYOwNZOwP  #7;;/W#XYZQwP[QwR  #7;;/_#`abSwRcSwT  #7;;/U#VWXUwTYUwV  #7;;/O#PQRWwVSWwX  #7;;/O#PQRYwXSYwZ  #7;;/P#QRS[wZT![wd "%Z%>!? @ewd ABewd CFjQ\F]B^A_ewd `aewd beeop}e~a  aAewdA(ewf ),J7H,I(J'KgwfL$gwl %(
>(B$C#DmwlE9mwn :=TB[=\]f=g9h8iown jlown mppt  vO  qP  Q]  q^  m_  l`own`owv E}UVwwvWww~ C_UVw~W"wH #&j&;"<!=IwH>	IwJ 
NZ5MN	NOKwJPKwN RTklmOwNnOwT }  @U  @C  ZB  YC  D  EUwTEUwZ <>S>qXpWqrs[wZt[w` LNi  OH  oG  nH  I  Jaw`J!awj "%Y]]8%<!= >kwj?	kwl 
UY]]<QS5TU	UVmwlWmwp *,ABCqwpDqwt DFYF{^z]{|}uwt~uwx EG[G}`|_}~ywx@yw~ EG[G}`|_}~w~@!wH "%VZZ%9!: ;IwH<.IwJ /2&**=Q2R.S-TKwJU	KwL 
RVZZb5QR	RSMwLTMwR 46F6`K_J`abSwRcSwV HJZJx_w^xyzWwV{WwZ MOc  PB  iA  hB  C  D[wZD[wb km{|}cwb~cwh 	DJJt23%PQRSTiwhUiwCp JQ	
(		#*

	sE   A0x#D4x('A+x-(Bx2Ax7B/x<B/yA1y"B yByc                 Z   t               } t        j                  d       t        j                  d       t        dz  j	                  t        j                  | dd      dz   d	       t        |       }t        d
z  j	                  |d	       t        d| d   d    d| d   d           y )NT)exist_okz%map_animation_exe_pattern_review.jsonF)r  :)r  
separatorsr  r4   r5   z%map_animation_exe_pattern_review.htmlzCwrote out/map_animation_exe_pattern_review.{json,html} tileSeqHits=r   r  r  r  )	r  OUTmkdirWEB
write_textr8   r  r)  print)r  	html_texts     r)   mainr4  M  s    <DIItIIItI22>>

4e
CdJ ?  D!I22>>ySZ>[		I'KLMQ	?45
6	8r+   __main__)r(   r   r_  r'   )r   )r(   z
int | Noner1   r   r_  r'   )r;   r   r<   r   r_  r   )rA   r[   rB   r[   r_  	list[int])r^   r6  r1   r'   r_  zbytes | None)rA   r[   r   r`  r_  dict[str, Any])rg  )rA   r[   r   r   r   r   r_  r'   )rA   r[   r   r`  r  r7  r_  r7  )
rA   r[   r   r`  r$  r   r%  r   r_  r`  )r  r7  r_  r`  )r_  r7  )r  z	list[str]r   zlist[list[Any]]r_  r'   )r  r7  r_  r'   )r_  None)5__doc__
__future__r   r%   r8   rS   syscollectionsr   pathlibr   typingr   r;   insertr'   __file__resolveparentbuild_map_animation_tile_reviewr   r   r	   probe_exe_scene_tablesr
   r   r   parentsr  r  r.  r0  r  r  r"   __annotations__r*   r2   r=   rE   r_   r   r   r  r+  rc  r  r  r  r  r)  r4  __name__r0   r+   r)   <module>rH     s  
 #    
    3tH~--/667 8 
 M L H~''*
]
Ul
Ul== DD 
 		' 	. 	18 4 .@"8
AH'6[
["[ %[ 	[|
"  	
 4jZ_D0fJZ
l^	" zF r+   