def get_3(item_to_fetch: Item):
    """
    Go someplace and pick something up that’s lying around there
    :param item_to_fetch:
    :return:
    """
    if item_to_fetch.place:
        dest = item_to_fetch.place
    elif item_to_fetch.belongs_to:
        # someone took it and put it in a specific place, put it where the NPC is
        Message.event(
            "Someone has stolen the item '%s' and put it somewhere else" %
            item_to_fetch)
        dest = item_to_fetch.belongs_to.place
        item_to_fetch.belongs_to = None
        item_to_fetch.place = dest
        item_to_fetch.save()
    else:
        # player already has the item or no one has it, put it in a random place
        Message.event(
            "Someone has stolen the item '%s' and has put it in a random place"
            % item_to_fetch)
        dest = Place.select().order_by(fn.Random()).get()
        item_to_fetch.place = dest
        item_to_fetch.save()

    player = Player.current()
    player.next_location = dest
    player.save()

    intel = Intel.construct(item_place=item_to_fetch)
    PlayerKnowledgeBook.get_or_create(player=player, intel=intel)
    Message.achievement("Intel '%s' learned" % intel.detail())

    # steps:
    # goto
    # gather
    steps = [[dest, None, item_to_fetch], [item_to_fetch]]
    Message.instruction("Gather '%s' from '%s'" % (item_to_fetch, dest))
    return steps
def goto_1(destination: Place, npc: NPC = None, item: Item = None):
    """
    You are already there.
    :return:
    """
    player = Player.current()
    if npc or item:
        event_dest_str = str(npc if npc else item) + ' (' + str(
            destination) + ')'
    else:
        event_dest_str = str(destination)

    if npc:
        # move the npc
        npc.place = player.place
        npc.save()
        intel = Intel.construct(npc_place=npc)
        PlayerKnowledgeBook.get_or_create(player=player, intel=intel)
        Message.debug("NPC (%s) moved to the player location (%s)" %
                      (npc, player.place))
        Message.event("%s moved to your location" % npc)
    elif item:
        # move item or the holder
        if item.belongs_to:
            holder = item.belongs_to  # type: NPC
            holder.place = player.place
            holder.save()
            intel = Intel.construct(npc_place=holder)
            PlayerKnowledgeBook.get_or_create(player=player, intel=intel)
            Message.debug(
                "Item (%s) holder (%s) moved to the player location (%s)" %
                (item, item.belongs_to, player.place))
            Message.event("Item '%s's holder moved to your location" % item)
        elif item.belongs_to_player:
            Message.debug("Player already has the item %s" % item)
            Message.event("You already have the item '%s'" % item)
        else:
            item.place = player.place
            item.save()
            intel = Intel.construct(item_place=item)
            PlayerKnowledgeBook.get_or_create(player=player, intel=intel)
            Message.debug("Item (%s) moved to the player location (%s)" %
                          (item, player.place))
            Message.event("Item '%s' has been moved to your location" % item)
    else:
        # update player's location
        player.place = destination
        player.save()
        Message.debug("Player moved to %s location" % event_dest_str)
        Message.event("Player has been moved to %s location" % destination)

    return [[]]
def goto_2(destination: Place, npc: NPC = None, item: Item = None):
    """
    Explore destination to find npc or item
    :return:
    """
    # place_location[1] is destination
    # area around location[1] is given to player to explore and find location[1]
    player = Player.current()

    # ensure player doesn't already know where the NPC or item is
    if npc:
        intel = Intel.construct(npc_place=npc)
        if PlayerKnowledgeBook.get_or_none(player=player, intel=intel):
            # player knows where the NPC is, move the NPC then
            npc.place = Place.select().where(Place.id != destination).order_by(
                fn.Random()).get()
            npc.save()
            destination = npc.place
            Message.event(
                "You just missed '%s' he has moved to somewhere else" % npc)
    elif item:
        intel = Intel.construct(item_place=item)
        if PlayerKnowledgeBook.get_or_none(player=player, intel=intel):
            # player knows where the Item is, move the item or item's holder
            if item.belongs_to:
                holder = item.belongs_to
                holder.place = Place.select().where(
                    Place.id != destination).order_by(fn.Random()).get()
                holder.save()
                destination = holder.place
                Message.event(
                    "Item '%s's holder just has been moved to somewhere else" %
                    item)
            else:
                item.place = Place.select().where(
                    Place.id != destination).order_by(fn.Random()).get()
                item.save()
                destination = item.place
                Message.event(
                    "Item '%s' just has been moved to somewhere else" % item)

    # steps:
    # T.explore
    steps = [[destination, npc, item]]
    Message.instruction("Explore around '%s'" % destination)
    return steps
def goto_3(destination: Place, npc: NPC = None, item: Item = None):
    """
    Find out where to go and go there.
    :return:
    """
    # place_location[1] is destination
    # location[1] is place_location[1] exact location
    player = Player.current()

    # find correct type of Intel from npc_place, item_place and place_location
    if npc:
        intel = Intel.get_or_none(type=IntelTypes.npc_place.name,
                                  npc_place=npc)
        if PlayerKnowledgeBook.get_or_none(player=player, intel=intel):
            # player already knows, move the npc
            destination = Place.select().where(Place.id != npc.place).order_by(
                fn.Random())
            if destination:
                destination = destination.get()
            else:
                destination = narrative_helper.create_place()
            npc.place = destination
            npc.save()
            # by moving NPC place, npc_place intel removes from player knowledge book automatically
            Message.event("NPC %s has moved to somewhere else" % npc)
    elif item:
        if item.belongs_to:
            intel = Intel.get_or_none(type=IntelTypes.npc_place.name,
                                      npc_place=item.belongs_to)
            if PlayerKnowledgeBook.get_or_none(player=player, intel=intel):
                # player already knows where the item holder is, move the npc
                holder = item.belongs_to
                destination = Place.select().where(
                    Place.id != holder.place).order_by(fn.Random())
                if destination:
                    destination = destination.get()
                else:
                    destination = narrative_helper.create_place()
                holder.place = destination
                holder.save()
                Message.debug(
                    "Item holder (%s) is moved somewhere else (item: %s)" %
                    (item.belongs_to, item))
                Message.event(
                    "Item '%s's holder has been just moved to somewhere else" %
                    item)
        else:
            intel = Intel.get_or_none(type=IntelTypes.item_place.name,
                                      item_place=item)
            if PlayerKnowledgeBook.get_or_none(player=player, intel=intel):
                # player already knows where the item is located at, move the item
                destination = Place.select().where(
                    Place.id != item.place).order_by(fn.Random())
                if destination:
                    destination = destination.get()
                else:
                    destination = narrative_helper.create_place()
                item.place = destination
                item.save()
                Message.event("Item '%s' has been misplaced" % item)
    else:
        intel = Intel.get_or_none(type=IntelTypes.location.name,
                                  place_location=destination)
        if PlayerKnowledgeBook.get_or_none(player=player, intel=intel):
            # player already knows where the place is exactly,
            # so create a new place at the same location with a different name, now player doesn't know!
            destination = Place.create(name=PlaceName.fetch_new(),
                                       x=destination.x,
                                       y=destination.y)
            intel = Intel.construct(place_location=destination)
            Message.event("Change of plans, destination is now '%s'" %
                          destination)

    if not intel:
        # create the correct type of intel based on what is being asked
        if npc:
            intel = Intel.construct(npc_place=npc)
        elif item and item.belongs_to:
            intel = Intel.construct(npc_place=item.belongs_to)
        elif item:
            intel = Intel.construct(item_place=item)
        else:
            intel = Intel.construct(place_location=destination)

    # update player's next location
    player.next_location = destination
    player.save()

    # steps:
    #   learn: location[1]
    #   T.goto: location[1]
    steps = [[intel], [destination]]

    if PlayParams.debug_mode and (npc or item):
        destination_str = str(npc if npc else item) + ' (' + str(
            destination) + ')'
    else:
        if npc:
            destination_str = npc
        elif item:
            destination_str = item
        else:
            destination_str = destination

    Message.instruction("Find out how to get to '%s' location, then go to it" %
                        destination_str)

    return steps