# Path: diplomacy/engine/utils.py
# def get_territory(sr_token):
#     if not sr_token:
#         return u''
#     return sr_token.split(u'.')[0]
# 
# def borders(sr_token):
#     return standard.connectivity.get(sr_token, ())
# 
# def territory_parts(t_token):
#     return standard.subregion_groups.get(t_token, ())
# 
# def has_land(sr_token):
#     return any(is_land(sr) for sr in territory_parts(get_territory(sr_token)))
# 
# def is_land(sr_token):
#     return sr_token.endswith('.l')


from collections import defaultdict, Counter
from itertools import combinations
from . import standard
from .utils import get_territory, borders, territory_parts, has_land, is_land
def find_convoys(units, fleets):
    """
    Generates pairs consisting of a cluster of adjacent non-coastal
    fleets, and the coastal territories that are reachable via convoy
    from that cluster.  This is necessary to determine legal orders.

    """
    fleets = [f for f in fleets if not has_land(f)]
    index = {f: {f} for f in fleets}

    # Calculate the connected sets of fleets
    for f1, f2 in combinations(fleets, 2):
        # If this pair is not adjacent, ignore it
        if f2 not in borders(f1):
            continue

        # If the sets for each of these fleets are not already the same set,
        # merge them and update the index
        if index[f1] != index[f2]:
            index[f1] |= index[f2]
            index.update((x, index[f1]) for x in index[f2])

    groups = {frozenset(S) for S in index.values()}

    armies = {u['subregion'] for u in units if u['u_type'] == 'A'}

    convoyable = []
    for gset in groups:
        coasts = {
            sr for f in gset

# Path: diplomacy/engine/utils.py
# def get_territory(sr_token):
#     if not sr_token:
#         return u''
#     return sr_token.split(u'.')[0]
# 
# def borders(sr_token):
#     return standard.connectivity.get(sr_token, ())
# 
# def territory_parts(t_token):
#     return standard.subregion_groups.get(t_token, ())
# 
# def has_land(sr_token):
#     return any(is_land(sr) for sr in territory_parts(get_territory(sr_token)))
# 
# def is_land(sr_token):
#     return sr_token.endswith('.l')


# Path: diplomacy/engine/digest.py
from collections import defaultdict, Counter
from itertools import combinations
from . import standard
from .utils import get_territory, borders, territory_parts, has_land, is_land

def find_convoys(units, fleets):
    """
    Generates pairs consisting of a cluster of adjacent non-coastal
    fleets, and the coastal territories that are reachable via convoy
    from that cluster.  This is necessary to determine legal orders.

    """
    fleets = [f for f in fleets if not has_land(f)]
    index = {f: {f} for f in fleets}

    # Calculate the connected sets of fleets
    for f1, f2 in combinations(fleets, 2):
        # If this pair is not adjacent, ignore it
        if f2 not in borders(f1):
            continue

        # If the sets for each of these fleets are not already the same set,
        # merge them and update the index
        if index[f1] != index[f2]:
            index[f1] |= index[f2]
            index.update((x, index[f1]) for x in index[f2])

    groups = {frozenset(S) for S in index.values()}

    armies = {u['subregion'] for u in units if u['u_type'] == 'A'}

    convoyable = []
    for gset in groups:
        coasts = {
            sr for f in gset

            for b in borders(f)