       return action1.player
   false
 
-# Returns true if this game is a draw, otherwise false. If the optional
-# addCurrentAction parameter is passed and set to "true", the check will
-# be made as if the current action were submitted.
+# Builds the "victors" array for the game. If the game is over, a list will be
+# returned containing the victorious or drawing players (which may be empty to
+# indicate that "nobody wins"). Otherwise, null is returned.
+noughts.getVictors = (game) ->
+  actionTable = makeActionTable(game._id)
+
+  # All possible winning lines in [column, row] format
+  victoryLines = [ [[0,0], [1,0], [2,0]], [[0,1], [1,1], [2,1]],
+      [[0,2], [1,2], [2,2]], [[0,0], [0,1], [0,2]], [[1,0], [1,1], [1,2]],
+      [[2,0], [2,1], [2,2]], [[0,0], [1,1], [2,2]], [[2,0], [1,1], [0,2]] ]
+
+  # Check for winner
+  for line in victoryLines
+    action1 = actionTable[line[0][0]][line[0][1]]
+    action2 = actionTable[line[1][0]][line[1][1]]
+    action3 = actionTable[line[2][0]][line[2][1]]
+    continue unless action1? and action2? and action3?
+    if action1.player == action2.player and action2.player == action3.player
+      return [action1.player]
+
+  # Check for draw
+  if noughts.Actions.find({gameId: game._id, submitted: true}).count() == 9
+    return game.players
+
+  # Game is not ending.
+  return null
+
+# Returns true if this game is a draw, otherwise false.
 noughts.isDraw = (gameId, addCurrentAction) ->
   return noughts.Actions.find({gameId: gameId, submitted: true}).count() == 9
 

    unless noughts.isCurrentActionLegal(gameId)
      die("Illegal action!")

    newPlayerNumber =
      if game.currentPlayerNumber == noughts.X_PLAYER
        noughts.O_PLAYER
      else
        noughts.X_PLAYER
    noughts.Actions.update game.currentAction,
      $set: {submitted: true}
    noughts.Games.update gameId,
      $set: {currentPlayerNumber: newPlayerNumber, currentAction: null}

  # Adds the provided command to the current action's command list. If there is
  # no current action, creates one. Any commands beyond the current location in


# Returns a 2-dimensional array of *submitted* game actions spatially indexed
# by [column][row], so e.g. table[0][2] is the bottom-left square's action.
makeActionTable = (gameId, currentActionId) ->
  result = [[], [], []]
  noughts.Actions.find({gameId: gameId, submitted: true}).forEach (action) ->
    for command in action.commands
