Skip to content

Commit d968512

Browse files
authored
Updated FindNoun to fix issue 356 (#366)
* Updated FindNoun to fix issue 356 * Fix exists check * Updated FindNoun to disallow circular references to alises
1 parent a005dbc commit d968512

File tree

2 files changed

+128
-101
lines changed

2 files changed

+128
-101
lines changed

internal/rooms/rooms.go

Lines changed: 86 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,153 +1580,138 @@ func (r *Room) FindContainerByName(containerNameSearch string) string {
15801580
}
15811581

15821582
func (r *Room) FindNoun(noun string) (foundNoun string, nounDescription string) {
1583-
15841583
if len(r.Nouns) == 0 {
1585-
return ``, ``
1584+
return "", ""
15861585
}
15871586

1587+
// Flatten the room nouns and create single-word aliases for multi-word nouns
15881588
roomNouns := map[string]string{}
1589-
15901589
for originalNoun, originalDesc := range r.Nouns {
15911590
roomNouns[originalNoun] = originalDesc
1592-
1593-
if strings.Contains(originalNoun, ` `) {
1594-
for _, n := range strings.Split(originalNoun, ` `) {
1595-
1596-
if _, ok := r.Nouns[n]; ok {
1591+
if strings.Contains(originalNoun, " ") {
1592+
for _, part := range strings.Split(originalNoun, " ") {
1593+
if _, exists := r.Nouns[part]; exists {
15971594
continue
15981595
}
1599-
1600-
if _, ok := roomNouns[n]; ok {
1596+
if _, exists := roomNouns[part]; exists {
16011597
continue
16021598
}
1603-
1604-
roomNouns[n] = `:` + originalNoun
1605-
1599+
roomNouns[part] = ":" + originalNoun
16061600
}
16071601
}
1608-
16091602
}
16101603

1604+
// Build candidate noun list
16111605
testNouns := util.SplitButRespectQuotes(noun)
1612-
ct := len(testNouns)
1613-
for i := 0; i < ct; i++ {
1614-
1615-
if splitCount := strings.Split(testNouns[i], ` `); len(splitCount) > 1 {
1616-
1617-
for _, n2 := range splitCount {
1618-
1619-
if len(n2) < 2 {
1620-
continue
1621-
}
1622-
1623-
testNouns = append(testNouns, n2)
1606+
for i := 0; i < len(testNouns); i++ {
1607+
if strings.Contains(testNouns[i], " ") {
1608+
for _, part := range strings.Split(testNouns[i], " ") {
1609+
testNouns = append(testNouns, strings.ToLower(strings.TrimSpace(part)))
16241610
}
1625-
16261611
}
16271612
}
1628-
1629-
// If it created more than one word, put the original back on as a full string to test
16301613
if len(testNouns) > 1 {
1631-
testNouns = append(testNouns, noun)
1614+
testNouns = append(testNouns, strings.ToLower(strings.TrimSpace(noun)))
16321615
}
16331616

1634-
for _, newNoun := range testNouns {
1617+
// Try each candidate: exact, singular/plural, alias-aware
1618+
for _, cand := range testNouns {
1619+
newNoun := strings.ToLower(strings.TrimSpace(cand))
16351620

1621+
// Direct match or single-level alias
16361622
if desc, ok := roomNouns[newNoun]; ok {
1637-
if desc[0:1] == `:` {
1638-
return desc[1:], roomNouns[desc[1:]]
1623+
if strings.HasPrefix(desc, ":") {
1624+
target := desc[1:]
1625+
if targetDesc, ok2 := roomNouns[target]; ok2 && !strings.HasPrefix(targetDesc, ":") {
1626+
return target, targetDesc
1627+
}
1628+
// alias->alias or missing target => ignore
1629+
} else {
1630+
return newNoun, desc
16391631
}
1640-
return newNoun, desc
1641-
}
1642-
1643-
if len(newNoun) < 2 {
1644-
continue
16451632
}
16461633

1647-
// If ended in `s`, strip it and add a new word to the search list
1648-
if newNoun[len(newNoun)-1:] == `s` {
1649-
1650-
testNoun := newNoun[:len(newNoun)-1]
1651-
if desc, ok := roomNouns[testNoun]; ok {
1652-
if desc[0:1] == `:` {
1653-
return desc[1:], roomNouns[desc[1:]]
1634+
// Strip "es"
1635+
if strings.HasSuffix(newNoun, "es") {
1636+
tn := strings.TrimSuffix(newNoun, "es")
1637+
if desc, ok := roomNouns[tn]; ok {
1638+
if strings.HasPrefix(desc, ":") {
1639+
target := desc[1:]
1640+
if targetDesc, ok2 := roomNouns[target]; ok2 && !strings.HasPrefix(targetDesc, ":") {
1641+
return target, targetDesc
1642+
}
1643+
} else {
1644+
return tn, desc
16541645
}
1655-
return testNoun, desc
16561646
}
1657-
16581647
} else {
1659-
1660-
testNoun := newNoun + `s`
1661-
if desc, ok := roomNouns[testNoun]; ok { // `s`` at end
1662-
if desc[0:1] == `:` {
1663-
return desc[1:], roomNouns[desc[1:]]
1648+
// Add "es"
1649+
tn := newNoun + "es"
1650+
if desc, ok := roomNouns[tn]; ok {
1651+
if strings.HasPrefix(desc, ":") {
1652+
target := desc[1:]
1653+
if targetDesc, ok2 := roomNouns[target]; ok2 && !strings.HasPrefix(targetDesc, ":") {
1654+
return target, targetDesc
1655+
}
1656+
} else {
1657+
return tn, desc
16641658
}
1665-
return testNoun, desc
16661659
}
1667-
16681660
}
16691661

1670-
// Switch ending of `y` to `ies`
1671-
if newNoun[len(newNoun)-1:] == `y` {
1672-
1673-
testNoun := newNoun[:len(newNoun)-1] + `ies`
1674-
if desc, ok := roomNouns[testNoun]; ok { // `ies` instead of `y` at end
1675-
if desc[0:1] == `:` {
1676-
return desc[1:], roomNouns[desc[1:]]
1662+
// "ies" -> "y"
1663+
if strings.HasSuffix(newNoun, "ies") {
1664+
tn := strings.TrimSuffix(newNoun, "ies") + "y"
1665+
if desc, ok := roomNouns[tn]; ok {
1666+
if strings.HasPrefix(desc, ":") {
1667+
target := desc[1:]
1668+
if targetDesc, ok2 := roomNouns[target]; ok2 && !strings.HasPrefix(targetDesc, ":") {
1669+
return target, targetDesc
1670+
}
1671+
} else {
1672+
return tn, desc
16771673
}
1678-
return testNoun, desc
16791674
}
1680-
1681-
}
1682-
1683-
if len(newNoun) < 3 {
1684-
continue
16851675
}
1676+
}
16861677

1687-
// Strip 'es' such as 'torches'
1688-
if newNoun[len(newNoun)-2:] == `es` {
1689-
1690-
testNoun := newNoun[:len(newNoun)-2]
1691-
if desc, ok := roomNouns[testNoun]; ok {
1692-
if desc[0:1] == `:` {
1693-
return desc[1:], roomNouns[desc[1:]]
1694-
}
1695-
return testNoun, desc
1696-
}
1697-
1698-
} else {
1699-
1700-
testNoun := newNoun + `es`
1701-
if desc, ok := roomNouns[testNoun]; ok { // `es` at end
1702-
if desc[0:1] == `:` {
1703-
return desc[1:], roomNouns[desc[1:]]
1678+
// Multi-word noun match
1679+
for full, desc := range roomNouns {
1680+
if strings.Contains(full, " ") {
1681+
for _, part := range testNouns {
1682+
if strings.Contains(full, part) {
1683+
if strings.HasPrefix(desc, ":") {
1684+
target := desc[1:]
1685+
if td, ok := roomNouns[target]; ok && !strings.HasPrefix(td, ":") {
1686+
return target, td
1687+
}
1688+
} else {
1689+
return full, desc
1690+
}
17041691
}
1705-
return testNoun, desc
17061692
}
1707-
1708-
}
1709-
1710-
if len(newNoun) < 4 {
1711-
continue
17121693
}
1694+
}
17131695

1714-
// Strip 'es' such as 'torches'
1715-
if noun[len(newNoun)-3:] == `ies` {
1716-
1717-
testNoun := newNoun[:len(newNoun)-3] + `y`
1718-
if desc, ok := roomNouns[testNoun]; ok { // `y` instead of `ies` at end
1719-
if desc[0:1] == `:` {
1720-
return desc[1:], roomNouns[desc[1:]]
1696+
// Single-word match for multi-word nouns
1697+
for full, desc := range roomNouns {
1698+
if !strings.Contains(full, " ") {
1699+
for _, part := range testNouns {
1700+
if part == full {
1701+
if strings.HasPrefix(desc, ":") {
1702+
target := desc[1:]
1703+
if td, ok := roomNouns[target]; ok && !strings.HasPrefix(td, ":") {
1704+
return target, td
1705+
}
1706+
} else {
1707+
return full, desc
1708+
}
17211709
}
1722-
return testNoun, desc
17231710
}
1724-
17251711
}
1726-
17271712
}
17281713

1729-
return ``, ``
1714+
return "", ""
17301715
}
17311716

17321717
func (r *Room) FindExitByName(exitNameSearch string) (exitName string, exitRoomId int) {

internal/rooms/rooms_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ func TestFindNoun(t *testing.T) {
108108
"mystery": "just a riddle",
109109
"secret": ":mystery", // chain alias -> :mystery
110110
"projector screen": "a wide, matte-white screen", // multi-word matching
111+
"island": "a tropical paradise",
112+
"rocks": ":island",
113+
"rocky island": ":island",
114+
"feet": ":hands",
115+
"hands": ":feet",
111116
},
112117
}
113118

@@ -209,6 +214,43 @@ func TestFindNoun(t *testing.T) {
209214
wantFoundNoun: "",
210215
wantDesc: "",
211216
},
217+
{
218+
name: "Multi-word input, first word valid (island)",
219+
inputNoun: "island",
220+
wantFoundNoun: "island",
221+
wantDesc: "a tropical paradise",
222+
},
223+
// Issue #356: Fix Noun aliases
224+
{
225+
name: "Multi-word input, first word valid (rocks)",
226+
inputNoun: "rocks",
227+
wantFoundNoun: "island",
228+
wantDesc: "a tropical paradise",
229+
},
230+
{
231+
name: "Multi-word input, first word valid (rocky island)",
232+
inputNoun: "rocky island",
233+
wantFoundNoun: "island",
234+
wantDesc: "a tropical paradise",
235+
},
236+
{
237+
name: "Multi-word input, first word valid (rocky)",
238+
inputNoun: "rocky",
239+
wantFoundNoun: "island",
240+
wantDesc: "a tropical paradise",
241+
},
242+
{
243+
name: "circular references (hands)",
244+
inputNoun: "hands",
245+
wantFoundNoun: "",
246+
wantDesc: "",
247+
},
248+
{
249+
name: "circular references (feet)",
250+
inputNoun: "feet",
251+
wantFoundNoun: "",
252+
wantDesc: "",
253+
},
212254
}
213255

214256
// Run each sub-test.

0 commit comments

Comments
 (0)