Я почти забыл самое простое решение
player-wins: [
"rock" "breaks" "scissors"
"paper" "covers"" rock"
"scissors" "cuts" "paper"
]
game: func [player1 player2] [
foreach [subject predicate object] player-wins [
all [
player1 = subject
player2 = object
return reduce [player1 predicate player2]
]
]
]
>> print game "rock" "scissors"
rock breaks scissors
>> print game "scissors" "paper"
scissors cut paper
Но и ваша вторая структура подходит
player-wins: [
["rock" "scissors"] "breaks"
["paper" "rock"] "covers"
["scissors" "paper"] "cut"
]
win: function [player1 player2] [
game: reduce [player1 player2]
winning: player-wins/(game)
print [player1 winning player2]
]
>> win "paper" "rock"
paper covers rock
или короткий
win: func [player1 player2] [
print [player1 select/only player-wins reduce [player1 player2] player2]
]
И оптимизированная версия, независимая от порядка, охватывающего все варианты, может быть такой:
player-wins: [
"rock" "breaks"
"scissors" "cuts"
"paper" "covers"
"rock" "is covered by"
"paper" "is cut by"
"scissors" "will be broken by" "rock"
]
game: func [player1 player2] [
parse player-wins [
collect [some [keep [player1 skip player2] | 2 skip] ]
]
]
>> print game "scissors" "rock"
scissors will be broken by rock
>> print game "rock" "scissors"
rock breaks scissors