| 12
 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
 111
 112
 113
 
 | import tutorial
 class Cargo extends string {
 Cargo() {
 this = "Nothing" or
 this = "Goat" or
 this = "Cabbage" or
 this = "Wolf"
 }
 }
 
 /** One of two shores. */
 class Shore extends string {
 Shore() {
 this = "Left" or
 this = "Right"
 }
 
 /** Returns the other shore. */
 Shore other() {
 this = "Left" and result = "Right"
 or
 this = "Right" and result = "Left"
 }
 }
 
 /** Renders the state as a string. */
 string renderState(Shore manShore, Shore goatShore, Shore cabbageShore, Shore wolfShore) {
 result = manShore + "," + goatShore + "," + cabbageShore + "," + wolfShore
 }
 
 /** A record of where everything is. */
 class State extends string {
 Shore manShore;
 Shore goatShore;
 Shore cabbageShore;
 Shore wolfShore;
 
 State() { this = renderState(manShore, goatShore, cabbageShore, wolfShore) }
 
 /** Returns the state that is reached after ferrying a particular cargo item. */
 State ferry(Cargo cargo) {
 cargo = "Nothing" and
 result = renderState(manShore.other(), goatShore, cabbageShore, wolfShore)
 or
 cargo = "Goat" and
 result = renderState(manShore.other(), goatShore.other(), cabbageShore, wolfShore)
 or
 cargo = "Cabbage" and
 result = renderState(manShore.other(), goatShore, cabbageShore.other(), wolfShore)
 or
 cargo = "Wolf" and
 result = renderState(manShore.other(), goatShore, cabbageShore, wolfShore.other())
 }
 
 /**
 * Holds if the state is safe. This occurs when neither the goat nor the cabbage
 * can get eaten.
 */
 predicate isSafe() {
 // The goat can't eat the cabbage.
 (goatShore != cabbageShore or goatShore = manShore) and
 // The wolf can't eat the goat.
 (wolfShore != goatShore or wolfShore = manShore)
 }
 
 /** Returns the state that is reached after safely ferrying a cargo item. */
 State safeFerry(Cargo cargo) { result = this.ferry(cargo) and result.isSafe() }
 
 /** man's move */
 string towards() {
 manShore = "Left" and result = "to the left"
 or
 manShore = "Right" and result = "to the right"
 }
 
 /**
 * Returns all states that are reachable via safe ferrying.
 * `path` keeps track of how it is achieved.
 * `visitedStates` keeps track of previously visited states and is used to avoid loops.
 */
 State reachesVia(string path, string visitedStates) {
 // Reachable in 1 step by ferrying a specific cargo
 exists(Cargo cargo |
 result = this.safeFerry(cargo) and
 visitedStates = result and
 path = "First " + cargo + " is ferried " + result.towards() + ","
 )
 or
 // Reachable by first following pathSoFar and then ferrying cargo
 exists(string pathSoFar, string visitedStatesSoFar, Cargo cargo |
 result = this.reachesVia(pathSoFar, visitedStatesSoFar).safeFerry(cargo) and
 // resulting state is not visited yet
 not exists(int i | i = visitedStatesSoFar.indexOf(result)) and
 visitedStates = visitedStatesSoFar + "_" + result and
 path = pathSoFar + "\nthen " + cargo + " is ferried " + result.towards() + ","
 )
 }
 }
 
 /** The initial state, where everything is on the left shore. */
 class InitialState extends State {
 InitialState() { this = renderState("Left", "Left", "Left", "Left") }
 }
 
 /** The goal state, where everything is on the right shore. */
 class GoalState extends State {
 GoalState() { this = renderState("Right", "Right", "Right", "Right") }
 }
 
 from string path
 where any(InitialState i).reachesVia(path, _) = any(GoalState g)
 select path + "."
 
 |