@@ -780,7 +780,7 @@ proc getphoto {name} {
780780array set customPhoto {}
781781
782782# List of {globpattern filepath} pairs for wildcard custom photo matching.
783- # Populated by loadCustomPhotos for any image filename containing "*" .
783+ # Populated by loadCustomPhotos for any image filename containing parentheses .
784784set customPhotoWild {}
785785
786786proc loadCustomPhotos {} {
@@ -790,19 +790,26 @@ proc loadCustomPhotos {} {
790790 #
791791 # Two filename conventions are supported:
792792 #
793- # 1. Exact match (no "*" in filename):
793+ # 1. Exact match (no parentheses in filename):
794794 # "Carlsen, Magnus.png" -> normalized and stored in ::customPhoto array
795- # "Martinus .png" -> normalized and stored in ::customPhoto array
795+ # "Smith .png" -> normalized and stored in ::customPhoto array
796796 # The name is normalized (lowercase, accents stripped, spaces removed) before
797797 # lookup, so "Carlsen, Magnus.png" matches a player named "Carlsen, Magnus".
798798 #
799- # 2. Wildcard match ("*" present in filename):
800- # "*stockfish*.png" -> matches any player name containing "stockfish"
801- # "Martinus*.png" -> matches any player name starting with "martinus"
802- # Patterns are stored in ::customPhotoWild and matched (case-insensitively)
803- # against the raw player name as it appears in the game header.
804- # Wildcards use Tcl's [string match] glob syntax (* matches any sequence of
805- # characters, ? matches any single character).
799+ # 2. Wildcard match (parentheses present in filename):
800+ # Parentheses act as wildcards (each () pair becomes * in the match pattern),
801+ # allowing flexible matching against the raw player name. This syntax is used
802+ # because "*" is illegal in filenames on Windows.
803+ #
804+ # "(stockfish).png" -> matches any player name containing "stockfish"
805+ # (pattern: *stockfish*)
806+ # "Smith().png" -> matches any player name starting with "Smith"
807+ # (pattern: smith*)
808+ # "()Stockfish().png" -> same as (stockfish).png, more explicit
809+ # (pattern: *stockfish*)
810+ #
811+ # Patterns are matched case-insensitively against the raw player name as it
812+ # appears in the game header (e.g., "Stockfish 17", "stockfish_elo3500").
806813 #
807814 # Priority: exact match wins over wildcard. Among wildcards, first file found wins.
808815
@@ -833,10 +840,15 @@ proc loadCustomPhotos {} {
833840
834841 set abspath [file normalize $imgfile ]
835842
836- if {[string first " *" $playername ] != -1} {
837- # Wildcard filename: store as a glob pattern matched against the
838- # lowercased raw player name (not comma-normalized).
839- lappend ::customPhotoWild [list [string tolower $playername ] $abspath ]
843+ if {[string first " (" $playername ] != -1} {
844+ # Wildcard filename: translate parentheses into * wildcards.
845+ # "(" and ")" each become "*", then collapse any "**" runs.
846+ set globpat [string tolower $playername ]
847+ set globpat [string map {" (" " *" " )" " *" } $globpat ]
848+ while {[string first " **" $globpat ] != -1} {
849+ set globpat [string map {" **" " *" } $globpat ]
850+ }
851+ lappend ::customPhotoWild [list $globpat $abspath ]
840852 } else {
841853 # Exact match: normalize as usual (handles accents, case, spaces)
842854 set key [normalizePhotoName $playername ]
@@ -928,8 +940,8 @@ proc normalizePlayerName { engine } {
928940# updatePlayerPhotos
929941# Updates the images photoW and photoB for the two players of the current game.
930942# Photo lookup proceeds in priority order:
931- # 1. Exact custom photo match (::customPhoto array, normalized name key)
932- # 2. Wildcard custom photo match (::customPhotoWild list, glob vs raw name )
943+ # 1. Exact custom photo match (::customPhoto array, normalized name key)
944+ # 2. Wildcard custom photo match (::customPhotoWild list, parentheses-derived glob )
933945# 3. SPF photo file fallback
934946#
935947proc updatePlayerPhotos {{force " " }} {
0 commit comments