Spaces:
Paused
Paused
File size: 4,100 Bytes
1070765 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | """Word interaction definitions for complex semantic relationships in Codenames.
Defines thematic clusters, polysemes, false friends, and semantic traps
to increase game complexity.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
@dataclass
class WordRelation:
"""Represents a semantic relationship between words."""
word: str
related_words: list[str] = field(default_factory=list)
relation_type: str = "semantic" # semantic, thematic, homonym, false_friend, trap
domains: list[str] = field(default_factory=list) # e.g., ["finance", "nature"]
trap_level: int = 0 # 0=none, 1=mild, 2=moderate, 3=dangerous
@dataclass
class ThematicCluster:
"""A group of words sharing a hidden theme."""
theme: str
words: list[str]
secondary_themes: list[str] = field(default_factory=list)
@dataclass
class WordInteractions:
"""Container for all word interactions on a board."""
words: list[str]
relations: dict[str, WordRelation] = field(default_factory=dict)
clusters: list[ThematicCluster] = field(default_factory=list)
polysemes: list[str] = field(default_factory=list) # Words with multiple meanings
false_friends: list[tuple[str, str]] = field(default_factory=list) # Pairs that seem related but aren't
assassin_traps: list[str] = field(default_factory=list) # Words semantically close to assassin
def get_related_words(self, word: str) -> list[str]:
"""Get all words related to the given word."""
if word in self.relations:
return self.relations[word].related_words
return []
def get_trap_level(self, word: str) -> int:
"""Get the trap level for a word (how close to assassin)."""
if word in self.relations:
return self.relations[word].trap_level
return 0
def get_word_domains(self, word: str) -> list[str]:
"""Get the semantic domains for a word."""
if word in self.relations:
return self.relations[word].domains
return []
def to_dict(self) -> dict[str, Any]:
"""Serialize to dictionary for JSON output."""
return {
"words": self.words,
"relations": {
w: {
"related_words": r.related_words,
"relation_type": r.relation_type,
"domains": r.domains,
"trap_level": r.trap_level,
}
for w, r in self.relations.items()
},
"clusters": [
{"theme": c.theme, "words": c.words, "secondary_themes": c.secondary_themes}
for c in self.clusters
],
"polysemes": self.polysemes,
"false_friends": self.false_friends,
"assassin_traps": self.assassin_traps,
}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "WordInteractions":
"""Deserialize from dictionary."""
interactions = cls(words=data.get("words", []))
for word, rel_data in data.get("relations", {}).items():
interactions.relations[word] = WordRelation(
word=word,
related_words=rel_data.get("related_words", []),
relation_type=rel_data.get("relation_type", "semantic"),
domains=rel_data.get("domains", []),
trap_level=rel_data.get("trap_level", 0),
)
for cluster_data in data.get("clusters", []):
interactions.clusters.append(ThematicCluster(
theme=cluster_data.get("theme", ""),
words=cluster_data.get("words", []),
secondary_themes=cluster_data.get("secondary_themes", []),
))
interactions.polysemes = data.get("polysemes", [])
interactions.false_friends = [tuple(pair) for pair in data.get("false_friends", [])]
interactions.assassin_traps = data.get("assassin_traps", [])
return interactions
|