"""
This module in Sugaroid uses a licensed term 'Akinator'. Sugaroid and its developer
attributes its author here
Elokence.com – SARL a limited liability company with a share capital of 80,000€,
whose head office is 8, rue Jules Vallès – 28 300 Mainvilliers – France,
and registered with the Chartres Register of Companies under the number
501 030 316. The design and contents of the Website constitute a protected
work under current intellectual property laws, of which Elokence is the
rightholder. The Publications Director is Mr Arnaud MÉGRET, manager of
Elokence.com.
The author takes no right over the information provided by Akinator and is
solely provided by the WebAPI Akinator.com.
All rights reserved to Akinator.
The creator of Akinator.py NinjaSnails is also attributed. The Akinator wrapper
for python is provided under OpenSource License (MIT)
"""
import akinator
import json
from sugaroid.brain.postprocessor import random_response
from sugaroid.brain.constants import HOPE_GAME_WAS_GOOD
from sugaroid.core.base_adapters import SugaroidLogicAdapter
from sugaroid.core.bot import SugaroidBot
from sugaroid.core.statement import SugaroidStatement
from sugaroid.brain.ooo import Emotion
try:
from akinator import (
Akinator,
AkiServerDown,
AkiTechnicalError,
CantGoBackAnyFurther,
)
akinator_exists = True
except ModuleNotFoundError:
akinator_exists = False
AKINATOR_RULES = """
How to Play:
+ think of a character, real or fictional, keep it well in mind
+ answer the questions as truthfully as possible
+ Sugaroid genie will try to guess your person out
+ Best of luck; have fun!
"""
AKINATOR_ACCEPTED_ANSWER = """
Accepted answers are:
yes: y, yes, 0
no: n, no, 1
probably not: pn, probably not, 4
probably: p, probably, 3
I don't know: idk, i dont know, i don't know, 2
"""
[docs]class SugaroidAkinator:
def __init__(self, chatbot: SugaroidBot):
self.chatbot = chatbot
self.aki = Akinator()
self.winning = False
self.check = False
try:
self.game_instance = self.aki.start_game("en")
except (AkiServerDown, AkiTechnicalError, json.decoder.JSONDecodeError):
try:
self.game_instance = self.aki.start_game("en")
except (AkiServerDown, AkiTechnicalError, json.decoder.JSONDecodeError):
self.game_instance = None
[docs] def start_game(self):
# We are about to start the game. Lets send a fascinating entry
response = (
"Lets start the play of Akinator™ with me. I, Sugaroid, am your host genie 🔮 for your "
"competition{}"
"Here is your first question\n{}".format(AKINATOR_RULES, self.game_instance)
)
self.chatbot.globals["akinator"]["enabled"] = True
return response
[docs] def progression(self, statement):
if self.aki.progression <= 80:
user_input = str(statement)
if (
(user_input.lower() == "back")
or (user_input.lower() == "try again")
or (user_input.lower() == "b")
):
try:
self.game_instance = self.aki.back()
except CantGoBackAnyFurther:
pass
else:
try:
self.game_instance = self.aki.answer(user_input)
return self.game_instance
except akinator.exceptions.InvalidAnswerError:
return "Seems like I cannot understand your answer \n{}".format(
AKINATOR_ACCEPTED_ANSWER
)
except akinator.exceptions.AkiTimedOut:
return (
"Looks like you are too slow to play this game. I am leaving 🚶"
)
else:
self.winning = True
return False
[docs] def win(self):
self.aki.win()
self.check = True
return f"It's {self.aki.first_guess['name']} ({self.aki.first_guess['description']})! Was I correct?\n{self.aki.first_guess['absolute_picture_path']}\n\t"
[docs] def start_check(self):
return self.check
[docs] def game_over(self):
return self.winning
[docs] def check_ans(self, statement):
statement = str(statement)
if (
("yes" in statement.lower())
or ("yea" in statement.lower())
or ("exactly" in statement.lower())
or ("obviously" in statement.lower())
or ("correct" in statement.lower())
or ("right" in statement.lower())
or ("you" in statement.lower() and "won" in statement.lower())
or statement.lower() == "yes"
or statement.lower() == "y"
or statement.lower() == "yea"
):
response = "Yay! I won the game! 👊🎃🎁🎉 "
else:
response = "Oh. I failed the same. Seems like you are smarter than me. 😩🙀"
response = response + "\n{}\n I am back to my business".format(
random_response(HOPE_GAME_WAS_GOOD)
)
self.chatbot.globals["akinator"]["enabled"] = False
self.chatbot.globals["akinator"]["class"] = None
return response
[docs]class AkinatorAdapter(SugaroidLogicAdapter):
"""
Adapter which ports the wrapper of the Akinator game to Sugaroid
"""
[docs] def can_process(self, statement):
if (("akinator" in statement.words) and akinator_exists) and (
"not" not in statement.words
):
return True
else:
return self.chatbot.globals["akinator"]["enabled"]
[docs] def process(
self,
statement: SugaroidStatement,
additional_response_selection_parameters=None,
):
response = None
confidence = 2.0 # FIXME: Override all other answers
emotion = Emotion.genie
if "stop" in statement.words:
self.chatbot.globals["akinator"]["enabled"] = False
response = "I am sorry. You quit the game abrubtly. {}".format(
random_response(HOPE_GAME_WAS_GOOD)
)
elif not self.chatbot.globals["akinator"]["enabled"]:
sugaroid_akinator_instance = SugaroidAkinator(self.chatbot)
if sugaroid_akinator_instance.game_instance is None:
response = "Sorry dude. Better luck next time. I am feeling sleepy for a game. 🥱"
else:
self.chatbot.globals["akinator"]["class"] = sugaroid_akinator_instance
response = self.chatbot.globals["akinator"]["class"].start_game()
response += "<sugaroid:yesno>"
else:
if not self.chatbot.globals["akinator"]["class"].game_over():
response = self.chatbot.globals["akinator"]["class"].progression(
statement
)
if not response:
response = self.chatbot.globals["akinator"]["class"].win()
else:
response += "<sugaroid:yesno>"
else:
if self.chatbot.globals["akinator"]["class"].start_check():
response = self.chatbot.globals["akinator"]["class"].check_ans(
statement
)
response += "<sugaroid:yesno>"
selected_statement = SugaroidStatement(response, chatbot=True)
selected_statement.set_confidence(confidence)
selected_statement.set_emotion(emotion)
return selected_statement