Return a NormalFormGame instance of the 2-player win-lose game,
    whose payoffs are either 0 or 1, introduced by Anbalagan et al.
    (2013). Player 0 has n actions, which constitute the set of nodes
    {0, ..., n-1}, while player 1 has n choose k actions, each
    corresponding to a subset of k elements of the set of n nodes. Given
    a randomly generated tournament graph on the n nodes, the payoff for
    player 0 is 1 if, in the tournament, the node chosen by player 0
    dominates all the nodes in the k-subset chosen by player 1. The
    payoff for player 1 is 1 if player 1's k-subset contains player 0's
    chosen node.

    Parameters
    ----------
    n : scalar(int)
        Number of nodes in the tournament graph.
    k : scalar(int)
        Size of subsets of nodes in the tournament graph.
    random_state : int or np.random.RandomState, optional
        Random seed (integer) or np.random.RandomState instance to set
        the initial state of the random number generator for
        reproducibility. If None, a randomly initialized RandomState is
        used.

    Returns
    -------
    g : NormalFormGame

    Notes
    -----
    The actions of player 1 are ordered according to the combinatorial
    number system [1]_, which is different from the order used in the
    original library in C.

    Examples
    --------
    >>> g = tournament_game(5, 2, random_state=1234)
    >>> g.players[0]
    Player([[ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
            [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  0.,  0.,  0.]])
    >>> g.players[1]
    Player([[ 1.,  1.,  0.,  0.,  0.],
            [ 1.,  0.,  1.,  0.,  0.],
            [ 0.,  1.,  1.,  0.,  0.],
            [ 1.,  0.,  0.,  1.,  0.],
            [ 0.,  1.,  0.,  1.,  0.],
            [ 0.,  0.,  1.,  1.,  0.],
            [ 1.,  0.,  0.,  0.,  1.],
            [ 0.,  1.,  0.,  0.,  1.],
            [ 0.,  0.,  1.,  0.,  1.],
            [ 0.,  0.,  0.,  1.,  1.]])

    References
    ----------
    .. [1] `Combinatorial number system
       <https://en.wikipedia.org/wiki/Combinatorial_number_system>`_,
       Wikipedia.

def tournament_game(n, k, random_state=None):
    """
    Return a NormalFormGame instance of the 2-player win-lose game,
    whose payoffs are either 0 or 1, introduced by Anbalagan et al.
    (2013). Player 0 has n actions, which constitute the set of nodes
    {0, ..., n-1}, while player 1 has n choose k actions, each
    corresponding to a subset of k elements of the set of n nodes. Given
    a randomly generated tournament graph on the n nodes, the payoff for
    player 0 is 1 if, in the tournament, the node chosen by player 0
    dominates all the nodes in the k-subset chosen by player 1. The
    payoff for player 1 is 1 if player 1's k-subset contains player 0's
    chosen node.

    Parameters
    ----------
    n : scalar(int)
        Number of nodes in the tournament graph.
    k : scalar(int)
        Size of subsets of nodes in the tournament graph.
    random_state : int or np.random.RandomState, optional
        Random seed (integer) or np.random.RandomState instance to set
        the initial state of the random number generator for
        reproducibility. If None, a randomly initialized RandomState is
        used.

    Returns
    -------
    g : NormalFormGame

    Notes
    -----
    The actions of player 1 are ordered according to the combinatorial
    number system [1]_, which is different from the order used in the
    original library in C.

    Examples
    --------
    >>> g = tournament_game(5, 2, random_state=1234)
    >>> g.players[0]
    Player([[ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
            [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  0.,  0.,  0.]])
    >>> g.players[1]
    Player([[ 1.,  1.,  0.,  0.,  0.],
            [ 1.,  0.,  1.,  0.,  0.],
            [ 0.,  1.,  1.,  0.,  0.],
            [ 1.,  0.,  0.,  1.,  0.],
            [ 0.,  1.,  0.,  1.,  0.],
            [ 0.,  0.,  1.,  1.,  0.],
            [ 1.,  0.,  0.,  0.,  1.],
            [ 0.,  1.,  0.,  0.,  1.],
            [ 0.,  0.,  1.,  0.,  1.],
            [ 0.,  0.,  0.,  1.,  1.]])

    References
    ----------
    .. [1] `Combinatorial number system
       <https://en.wikipedia.org/wiki/Combinatorial_number_system>`_,
       Wikipedia.

    """
    m = scipy.special.comb(n, k, exact=True)
    if m > np.iinfo(np.intp).max:
        raise ValueError('Maximum allowed size exceeded')

    payoff_arrays = tuple(np.zeros(shape) for shape in [(n, m), (m, n)])
    tourn = random_tournament_graph(n, random_state=random_state)
    indices, indptr = tourn.csgraph.indices, tourn.csgraph.indptr
    _populate_tournament_payoff_array0(payoff_arrays[0], k, indices, indptr)
    _populate_tournament_payoff_array1(payoff_arrays[1], k)
    g = NormalFormGame(
        [Player(payoff_array) for payoff_array in payoff_arrays]
    )
    return g