
    0j                    l    d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 dZ
dZdddZddZddZddZdS )u\  世界包(World Pack)接入规范的发现与校验 —— 多世界平台的准入闸口。

一个"世界包"= `worlds/<id>/` 目录,自描述一个可玩世界。契约见 docs/world-pack-spec.md。
平台靠本模块**发现**可玩世界、**校验**世界包是否合规(再决定能否加载),从而做到
"加新世界纯靠丢一个目录、不改引擎"(开闭原则)。

设计:校验只读数据、不构造引擎;返回问题清单(空=合规)。错误([E])阻断加载,
警告([W])可加载但提示作者。引擎运行期对缺失项一律有回退(向前兼容),故多数文件可选。
    )annotationsN)Path)WorldBuilder)ManifestError)
charactersplaces)	acts.json
items.json
world.jsonzviz.jsonz
beats.jsonworldsroot
str | Pathreturn	list[str]c                T   t          |           } |                                 sg S g }t          |                                           D ]^}|                                rH|dz                                  r1|dz                                  r|                    |j                   _|S )uY   列出 root 下所有看起来像世界包的子目录 id(含 characters/ 与 places/)。r   r   )r   is_dirsortediterdirappendname)r   outds      -/root/genesis-world/src/genesis/world/pack.pydiscover_worldsr      s    ::D;;== 	
CDLLNN##  88:: 	1|+3355 	1x<:O:O:Q:Q 	JJqvJ    pathr   tuple[dict | None, str | None]c                    |                                  sdS 	 t          j        |                     d                    d fS # t          j        t
          f$ r}d | j         d| fcY d }~S d }~ww xY w)N)NNzutf-8)encodingu    不是合法 JSON:)existsjsonloads	read_textJSONDecodeErrorOSErrorr   )r   es     r   
_load_jsonr'   $   s    ;;== z:z$..'.::;;TAA '* : : :	99a999999999:s   )A A0A+%A0+A0	world_dirc                F   t          |           } g |                                 sd|  gS t          D ]2}| |z                                  s                    d| d           3t	          d D                       rS 	 t          j        t          |                     }|                                 n # t          $ r}d| gz   cY d}~S d}~ww xY wd |j
                                        D             d |j                                        D             }t                      }|s                    d	           s                    d
           dAdBfd}t          | dz            \  }}|r                    d|            nY|rV|                    dg           D ]2}	|	                    d          r|                    |	d                    3 |dd |                    dg           D                        |                    dg           D ]7}
|
                    d          r  |d|
                    d          g           8|                    dg           D ]~}
|
                    d          pi                                 D ]R\  }}|                    d          }|r6||vr2                    d|
                    d           d| d| d            St          | d!z            \  }}|r                    d|            n|r |d"t%          |                    d#          pi                                           d$            |d%|                    d&          pg d$            |d'|                    d(          pg d$            |d)|                    d*          pg d$           t          | d+z            \  }}|r                    d|            nB|r?|                    d,g           D ]}|                    d-          }|r3||vr/                    d.|                    d/           d0| d1            |d2|                    d/           d3|                    d          pg d$           |                    d4          pi                                 D ]y\  }}|d5k    r||vr                    d6| d7           t)          |t*                    r|pi                     d8          nd}|r |vr                    d9| d:| d;           zd< |j                                        D             }|s                    d=           n,t-          |          d>k    r                    d?| d@           S )Cu   校验一个世界包是否合规。返回问题清单(空=完全合规)。
    [E]=错误(应阻断加载);[W]=警告(可加载,建议修)。u   [E] 世界目录不存在:u   [E] 缺少必需目录 /c              3  @   K   | ]}|                     d           V  dS )u   [E] 缺少必需目录N
startswith.0is     r   	<genexpr>z!validate_world.<locals>.<genexpr>7   s/      
B
Ba1<<011
B
B
B
B
B
Br   u   [E] manifest 校验失败:Nc                    h | ]	}|j         
S  r   )r/   pms     r   	<setcomp>z!validate_world.<locals>.<setcomp>@   s    ===r27===r   c                    h | ]	}|j         
S r3   r4   r/   cms     r   r6   z!validate_world.<locals>.<setcomp>A   s    <<<"bg<<<r   u   [E] 没有任何角色u   [E] 没有任何地点Elabelstrsevr   Nonec           
     \    |D ]'}|r#|vr                     d| d|  d| d           (d S )N[z] u    引用了不存在的地点「   」)r   )r;   namesr=   nissuesplace_namess       r   _check_placesz%validate_world.<locals>._check_placesH   sb     	W 	WA WQk))U#UUUUqUUUVVV	W 	Wr   r
   z[E] itemsidu   items.json 物品c                8    g | ]}|                     d           S )place)get)r/   its     r   
<listcomp>z"validate_world.<locals>.<listcomp>V   s"    +]+]+]BFF7OO+]+]+]r   
facilitiesrJ   u   items.json 设施verbsreveal_itemu   [W] 设施 u    的动词「u'   」reveal_item 指向未定义物品「rA   r   zworld.json place_causeplace_causeWzworld.json conspicuousconspicuouszworld.json ceremonial_venuesceremonial_venueszworld.json secret_passagessecret_passagesr	   	kill_actstargetu   [E] acts.json 第actu   幕 target「u   」不在角色名册内u   acts.json 第u   幕取景地dossier_docu   [E] acts.json dossier 角色「u   」不在名册内evidence_placeu   [W] acts.json dossier「u   」的 evidence_place「u   」不是已知地点c                2    g | ]}d |j         pdv |j        S )u   凶手 )roler   r8   s     r   rM   z"validate_world.<locals>.<listcomp>~   s+    \\\2RW]XZ@[@[rw@[@[@[r   uW   [W] 没有 role 含「凶手」的角色(推理类世界通常需要一名隐藏凶手)   u   [W] 有多名凶手角色 u-   (引擎按第一名处理,确认是否有意))r:   )r;   r<   r=   r<   r   r>   )r   r   REQUIRED_DIRSr   anyr   from_directoryr<   validate_refsr   r   valuesr   setr'   rK   addrG   listkeys
isinstancedictlen)r(   r   builderr&   rosteritem_idsrF   rG   errrL   fverbspecriwcfgactsatr   epkillersrD   rE   s                        @@r   validate_worldrz   -   s    YIF :8Y8899 : :A%%'' 	:MM8A888999

B
B6
B
B
BBB ;-c)nn== ; ; ;9a99::::::::;==W^%:%:%<%<===K<< 2 9 9 ; ;<<<FH 0./// 0.///W W W W W W W W I455JE3
 @lSll####	 @))GR(( 	' 	'Bvvd|| 'RX&&&)+]+]eiiPWY[F\F\+]+]+]^^^<,, 	E 	EAuuW~~ E1AEE'NN3CDDD<,, 	@ 	@A uuW~~3::<< @ @
dXXm,, @"H,,MM"~d"~"~$"~"~wy"~"~"~@ 9|344ID#
 \lSll####	 \.dhh}6M6M6SQS5Y5Y5[5[0\0\^abbb.0G0G0M2sSSS4dhh?R6S6S6YWY[^___2DHH=N4O4O4USUWZ[[[ 9{233ID#
 rlSll####	 r+r** 	a 	aAhA jQf__h!%%,,hhQhhhiiiMD!%%,,DDDaeeGnnFZXZ\_````++1r88:: 	r 	rGD!v~~6!!XXXXYYY4>q$4G4GQ!'r/000TB rb++pppWYpppqqq ]\!3!:!:!<!<\\\G kopppp	W		i7iiijjjMs   5B: :
CCCCrj   c                   t          |           } t          |           }| j        g d| dz                                  t	          d |D                        |d}	 t          j        t          |                     }t          d |j	        
                                D                       |d<   t          |j                  |d<   n# t          $ r Y nw xY w|S )uZ   给平台的世界列表用:返回 {id, roster, places, has_acts, valid, issues} 概要。r   r	   c              3  @   K   | ]}|                     d           V  dS )z[E]Nr,   r.   s     r   r1   z!describe_world.<locals>.<genexpr>   s.      AAQQ\\%00AAAAAAr   )rH   rm   r   has_actsvalidrD   c              3  $   K   | ]}|j         V  d S )Nr4   r8   s     r   r1   z!describe_world.<locals>.<genexpr>   s$      NNBNNNNNNr   rm   r   )r   rz   r   r    ra   r   rb   r<   r   r   rd   rk   r   r   )r(   rD   inforl   s       r   describe_worldr      s    YII&&F.B!)VaJaIiIiIkIkAA&AAAAAAVU UD-c)nn==NN'2D2K2K2M2MNNNNNXW^,,X   Ks   A+C 
CC)r   )r   r   r   r   )r   r   r   r   )r(   r   r   r   )r(   r   r   rj   )__doc__
__future__r   r!   pathlibr   genesis.manifest.builderr   genesis.manifest.schemar   r`   OPTIONAL_FILESr   r'   rz   r   r3   r   r   <module>r      s     # " " " " "        1 1 1 1 1 1 1 1 1 1 1 1 )T	 	 	 	 	: : : :W W W Wt     r   