#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Make me an omelette. A Amazon Alexa Skill Game implementet as a AWS Lamda function.
You are in a virtual kitchen and your goal is to cook a omelette.
author: Kolja Lubitz
e-mail: pinguin999@gmail.com
"""
from __future__ import print_function
#Lebewesesn
#Es könnte ein kleiner Troll in der Vorratskammer sein
#Verbesserungsmöglichkeit:
#Beim Raumwechsel wird der aktuelle Raum mit seinem Status in die DB geladen
#Der neue Raum wird aus der DB und den Session Informationen zusammen gesetzt und in die Session geladen
#Alle Operationen arbeiten dann auf der Session
#Look at sollte auch inventory bekommen und dann den inhalt vorlesen
#Merge Use und use_object zu einem Intend
#der cupboard ist Verschlossen wo ist der Schlüssel?
#Bei Counter events sollte obj und room nicht übergeben werden
#Event für zwischensequenzen. Das event wird immer angesprochen und muss selber checken ob es sich ausführt.
#Event types: all all_move all_use ...
#Raumverbindungen machen kein sinn. Man sollte immer von überall nach überall kommen können. Sonst müsste man dem spieler immer sagen wo man hin kann.
rooms = {"rooms": [\
{"name": "kitchen", "objects": ["table", "fridge", "cupboard", "oven"]},
{"name": "storeroom", "objects": ["cupboard"]},
]}
# Es fehlen noch die sätze für:
#Kann ich nicht aufheben
#Die description sollte optional eine Liste sein damit immer mal was anderes als antwort gegeben wird
#Die auflistung im inventar. Example: I have a recipe, eggs and a table.
objects = {"objects": [\
{"name": "table", "description": "A dining table. Please put the final omelette on the table.", "collectable": False}, \
{"name": "recipe", "description": "omelette recipe. For an omelette you need eggs, salt, pepper, and grated cheese. Mix all and fry it in a pan with a little bit oil", "collectable": False}, \
{"name": "fridge", "description": "The fridge. Maybe you have some eggs and cheese in the fridge.", "collectable": False}, \
{"name": "cupboard", "description": "A cupboard", "collectable": False}, \
{"name": "eggs", "description": "Yea eggs. You need the aggs for the omelette.", "collectable": True}, \
{"name": "salt", "description": "The salt. Do not put to much salt into the omelette.", "collectable": True}, \
{"name": "pepper", "description": "The pepper. With the pepper your omelette get this special taste.", "collectable": True}, \
{"name": "oil", "description": "The Oil. You need the oil to get your omelette crusty.", "collectable": True}, \
{"name": "cheese", "description": "Delicious cheese. Every omelette needs cheese.", "collectable": True}, \
{"name": "cheese grater", "description": "The cheese grater is needed to get the cheese into small peaces.", "collectable": True}, \
{"name": "grated cheese", "description": "This cheese is nicely grated", "collectable": False}, \
{"name": "pan", "description": "The pan. Fry the raw omelette in pan.", "collectable": True}, \
{"name": "pasta", "description": "The pasta, Ohh this item is from an other game.", "collectable": False}, \
{"name": "cookbook", "description": "The cookbook. In the cookbook you can find a lot of recipes. But you only have the ingredients for omelette.", "collectable": False}, \
{"name": "stove", "description": "Use the stove if you have all ingredients for your omelette.", "collectable": False}, \
{"name": "oven", "description": "On this oven I can fry my omelette.", "collectable": False}, \
{"name": "omelette", "description": "Wow this omelette looks very delicious.", "collectable": False}, \
]}
combinations = { "combinations": [\
{"in": ["cheese", "cheese grater"], "out": "grated cheese"},\
]}
# Events
# A event hast two speech_outs one for sucsess and fail.
events = { "events": [\
{"object": "fridge", "room": "kitchen", "event_name": "", "event":"open_fridge", "sucsess": "Oh I found eggs and cheese. I will take them with me.", "fail": ""},\
{"object": "cupboard", "room": "kitchen", "event_name": "", "event":"open_cupboard_kitchen", "sucsess": "Oh I found a pan. I will take it with me.", "fail": ""},\
{"object": "cupboard", "room": "storeroom", "event_name": "", "event":"open_cupboard_storeroom", "sucsess": "There is a old cookbook and a pack of pasta. I don't need that stuff to cook an omelette. Maybe thats part of an other game... But there is also a cheese grater that looks handy. I will take it with me.", "fail": "There is a old cookbook and a pack of pasta. I don't need that stuff to cook an omelette. Maybe thats part of an other game..."},\
{"object": "", "room": "", "event_name": "look_at_table", "event":"look_at_table", "sucsess": "Oh, there is also salt and pepper ", "fail": "And yes, I already have the salt and pepper."},\
{"object": "", "room": "", "event_name": "combine_tabele_omelette", "event":"finish_game", "sucsess": "You made it. You master the game. Now you can exit the game by saying 'exit game' or you can stay in the game and continue exploring it.", "fail": "Oh no the omelette ist still raw."},\
{"object": "", "room": "", "event_name": "combine_omelette_table", "event":"finish_game", "sucsess": "You made it. You master the game. Now you can exit the game by saying 'exit game' or you can stay in the game and continue exploring it.", "fail": "Oh no the omelette ist still raw."},\
{"object": "", "room": "", "event_name": "combine_pan_oven", "event":"cook", "sucsess": "You are cooking an omelette.", "fail": "I still need ingredients, look in your recipe how to cook a omelette."},\
{"object": "", "room": "", "event_name": "combine_oven_pen", "event":"cook", "sucsess": "You are cooking an omelette.", "fail": "I still need ingredients, look in your recipe how to cook a omelette."},\
]}
def lambda_handler(event, context):
""" Route the incoming request based on type (LaunchRequest, IntentRequest,
etc.) The JSON body of the request is provided in the event parameter.
"""
#print("event.session.application.applicationId=" +
# event['session']['application']['applicationId'])
"""
Uncomment this if statement and populate with your skill's application ID to
prevent someone else from configuring a skill that sends requests to this
function.
"""
#if (event['session']['application']['applicationId'] != "amzn1.echo-sdk-ams.app.ec0546ac-0d52-407c-af91-8da82b083c60"):
# raise ValueError("Invalid Application ID")
if event['request'] == None or event['session'] == None:
session_attributes = session['attributes']
should_end_session = False
speech_output = "Sorry I don't understnd what do you try to do."
reprompt_text = "Sorry I don't understnd what do you try to do."
return build_response(session_attributes, build_speechlet_response(
intent['name'], speech_output, reprompt_text, should_end_session))
if event['session']['new']:
on_session_started({'requestId': event['request']['requestId']},
event['session'])
if event['request']['type'] == "LaunchRequest":
return on_launch(event['request'], event['session'])
elif event['request']['type'] == "IntentRequest":
return on_intent(event['request'], event['session'])
elif event['request']['type'] == "SessionEndedRequest":
return on_session_ended(event['request'], event['session'])
def on_session_started(session_started_request, session):
""" Called when the session starts """
print("on_session_started requestId=" + session_started_request['requestId']
+ ", sessionId=" + session['sessionId'])
def on_launch(launch_request, session):
""" Called when the user launches the skill without specifying what they
want
"""
print("on_launch requestId=" + launch_request['requestId'] +
", sessionId=" + session['sessionId'])
# Dispatch to your skill's launch
return get_welcome_response()
def on_intent(intent_request, session):
""" Called when the user specifies an intent for this skill """
print("on_intent requestId=" + intent_request['requestId'] +
", sessionId=" + session['sessionId'])
try:
session['attributes']['event_counter']
except:
session['attributes'] = {"room": "kitchen", "inventory": ["recipe"], "event_counter": {"welcome": 1} }
intent = intent_request['intent']
intent_name = intent_request['intent']['name']
# Dispatch to your skill's intent handlers
if intent_name == "move":
return move(intent, session)
elif intent_name == "look_around":
return look_around(intent, session)
elif intent_name == "look_at":
return look_at(intent, session)
elif intent_name == "pick_up":
return pick_up(intent, session)
elif intent_name == "use":
return use(intent, session)
elif intent_name == "inventory":
return inventory(intent, session)
elif intent_name == "combine":
return combine(intent, session)
elif intent_name == "use_object":
return use_object(intent, session)
elif intent_name == "AMAZON.HelpIntent":
return get_help_response(intent, session)
elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
return handle_session_end_request()
else:
raise ValueError("Invalid intent")
def on_session_ended(session_ended_request, session):
""" Called when the user ends the session.
Is not called when the skill returns should_end_session=true
"""
print("on_session_ended requestId=" + session_ended_request['requestId'] +
", sessionId=" + session['sessionId'])
# add cleanup logic here
#TODO Save session to DB
# --------------------------------- Events -------------------------------------
#Salz und Pfeffer stehen auf dem Tisch. Um die nehmen zu können muss man einmal look at auf den Tisch aufgerufen haben.
def open_fridge(intent, session, obj, room):
if not "cheese" in session['attributes']['inventory'] and not "grated cheese" in session['attributes']['inventory']:
session['attributes']['inventory'].append("cheese")
if not "eggs" in session['attributes']['inventory']:
session['attributes']['inventory'].append("eggs")
return True
def open_cupboard_kitchen(intent, session, obj, room):
if not "pan" in session['attributes']['inventory']:
session['attributes']['inventory'].append("pan")
return True
def open_cupboard_storeroom(intent, session, obj, room):
if not "cheese grater" in session['attributes']['inventory']:
session['attributes']['inventory'].append("cheese grater")
return True
return False
def look_at_table(intent, session, obj, room):
if not "salt" in session['inventory'] and not "pepper" in session['inventory']:Complete list of actions to complete the game.
session['inventory'].append("salt")
session['inventory'].append("pepper")
return True
return False
def finish_game(intent, session, obj, room):
return True
def cook(intent, session, obj, room):
if "salt" in session['inventory'] \
and "pepper" in session['inventory'] \
and "eggs" in session['inventory'] \
and "pan" in session['inventory'] \
and "grated cheese" in session['inventory']:
session['inventory'].append("omelette")
session['inventory'].remove("salt")
session['inventory'].remove("pepper")
session['inventory'].remove("eggs")
session['inventory'].remove("pan")
session['inventory'].remove("grated cheese")
return True
return False
# ---------------------------------- Logic -------------------------------------
def is_object_in_room(room_in, obj_in):
for room in rooms['rooms']:
if (room['name']) == room_in:
for obj in room['objects']:
if (obj) == obj_in:
return True
return False
def is_object_in_inventory(inventory, obj_in):
for obj in inventory:
if obj == obj_in:
return True
return False
def object_description(obj_in):
for obj in objects['objects']:
if (obj['name']) == obj_in:
return obj['description']
return None
def is_object_collectable(room_in, obj_in):
if is_object_in_room(room_in, obj_in):
for obj in objects['objects']:
if (obj['name']) == obj_in:
if obj['collectable'] == True:
return True
return False
def handle_event(intent, session, event, obj = None, room = None):
event_handler = None
try:
#print (locals())
#print ("------------------")
#print (globals())
event_handler = globals().get(event['event'])
except AttributeError:
raise NotImplementedError("Event '{}' is not implemented.".format(event_name))
if event_handler(intent, session, obj, room):
return event["sucsess"]
else:
return event["fail"]
def use_object_in_room(intent, session, obj, room):
for event in events['events']:
if event['object'] == obj and event['room'] == room:
return handle_event(intent, session, event, obj, room)
return False
def event_counter(intent, session, action, value = ''):
event_value = action + '_' + value
#print(intent)
#print(session)
#print(event_value)
try:
session['event_counter'][event_value] = int(session['event_counter'][event_value]) + 1
except KeyError:
session['event_counter'][event_value] = 1
for event in events['events']:
if event['event_name'] == event_value:
return handle_event(intent, session, event)
return ""
def get_event_count(session, event, value = ''):
try:
return session['event_counter'][event + '_' + value]
except KeyError:
return 0
# --------------- Functions that control the skill's behavior ------------------
def get_welcome_response():
""" Init the session with start room and inventory items."""
session_attributes = {"room": "kitchen", "inventory": ["recipe"], "event_counter": {"welcome": 1} }
card_title = "Welcome to 'Make me an omelette'."Complete list of actions to complete the game.
speech_output = "Welcome to make me an omelette. " \
"You are in a kitchen and your quest is to make an omeltt. " \
"You should look around to learn more about the enviroment, "\
"you can also move to the storeroom by saying 'move to storeroom' or back by saying 'move to kitchen'. " \
"Please command all aktions until you fullfill the quest. The game will not ask you every time for your next step."
# If the user either does not reply to the welcome message or says something
# that is not understood, they will be prompted again with this text.
reprompt_text = "Welcome to make me a omelette."
should_end_session = False
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def get_help_response(intent, session):
card_title = "How to play"
speech_output = "'Make me an omelette' is a speach adventure game. In this game your quest is to make an omelette and place it at the dining table in the kitchen. " \
"You are in a kitchen and next to the kitchen is a storeroom. If you want to learn more about your envirement just say 'look around'. " \
"If you are not sure how to cook an omelette just look at the recipe in your inventory, by saying 'look at recipe'. " \
# Setting this to true ends the session and exits the skill.
should_end_session = False
return build_response({}, build_speechlet_response(
card_title, speech_output, None, should_end_session))
def handle_session_end_request():
card_title = "Game End"
speech_output = "Thank you for playing 'Make me an omelette'. At the moment there" \
" is no possibility to save the game, so you have to start from the beginning next time."
# Setting this to true ends the session and exits the skill.
should_end_session = True
return build_response({}, build_speechlet_response(
card_title, speech_output, None, should_end_session))
def move(intent, session):
session_attributes = session['attributes']
if 'value' in intent['slots']['room']:Complete list of actions to complete the game.
event_speech = event_counter(intent, session_attributes, "move", intent['slots']['room']['value'])
else:
event_speech = event_counter(intent, session_attributes, "move", 'None')
should_end_session = False
if 'room' in intent['slots']:
room = intent['slots']['room']['value']
session_attributes['room'] = room
speech_output = "You are moving to the " + room + "."
reprompt_text = "You can move to an other room by saying, " \
"move to, plus the rooms name?"
else:
speech_output = "I'm not sure where you want to go. " \
"Here are only the kitchen and the storeroom."
reprompt_text = "I'm not sure wher you want to go. " \
"You can move to an other room by saying, " \
"move to, plus the rooms name?"
return build_response(session_attributes, build_speechlet_response(
'Move', speech_output, reprompt_text, should_end_session))
def look_around(intent, session):
session_attributes = session['attributes']
event_counter(intent, session_attributes, "look_around")
should_end_session = False
items = "You can see "
for room in rooms['rooms']:
if (room['name']) == session_attributes['room']:
objects = room['objects']
for obj in objects[:-1]:
items += obj + " "
if len(objects) > 1:
items += "and " + objects[-1:][0]
else:
items += objects[-1:][0]
speech_output = "You are in the " + session_attributes['room'] + ". " + items
reprompt_text = "Say where am I to learn more about your enviroment."
return build_response(session_attributes, build_speechlet_response(
'Look around', speech_output, reprompt_text, should_end_session))
def look_at(intent, session):
session_attributes = session['attributes']
if 'value' in intent['slots']['object']:
event_speech = event_counter(intent, session_attributes, "look_at", intent['slots']['object']['value'])
else:
event_speech = event_counter(intent, session_attributes, "look_at", 'None')
should_end_session = False
if 'object' in intent['slots'] and 'value' in intent['slots']['pick_up']:
obj = intent['slots']['object']['value']
if is_object_in_room(session_attributes['room'], obj) or is_object_in_inventory(session_attributes['inventory'], obj):
discription = object_description( obj)
if discription:
speech_output = discription + " " + event_speech
else:
speech_output = "I have no idea what that is, jet?"
else:
speech_output = "There is no " + obj + " here."
reprompt_text = "You can look at all objects in the room you are in and the objects in your inventory."
else:
speech_output = "I'm not sure where you want to look at. " \
"Please try again."
reprompt_text = "I'm not sure where you want to look at. " \
"You can look at all objects in the room you are in and the objects in your inventory by saying, " \
"look at, plus the objects name?"
return build_response(session_attributes, build_speechlet_response(
'Look at', speech_output, reprompt_text, should_end_session))
def pick_up(intent, session):
session_attributes = session['attributes']
if 'value' in intent['slots']['object']:
event_counter(intent, session_attributes, "pick_up", intent['slots']['object']['value'])
else:
event_counter(intent, session_attributes, "pick_up", 'None')
should_end_session = False
if 'object' in intent['slots'] and 'value' in intent['slots']['object']:
obj = intent['slots']['object']['value']
if is_object_collectable(session_attributes['room'], obj):
session_attributes['inventory'].append(obj)
speech_output = "I put that to good ues."
else:
speech_output = "I can not take " + obj + " with me."
reprompt_text = "You can pick up objects in the room you are in."
else:
speech_output = "I'm not sure what you want to pick up. " \
"Please try again."
reprompt_text = "I'm not sure what you want to pick up. " \
"You can pick up all objects in the room you are in by saying: " \
"'pick up plus the objects name'"
return build_response(session_attributes, build_speechlet_response(
'Pick up', speech_output, reprompt_text, should_end_session))
def use(intent, session):
session_attributes = session['attributes']
if 'value' in intent['slots']['object']:
event_counter(intent, session_attributes, "use", intent['slots']['object']['value'])
else:
event_counter(intent, session_attributes, "use", 'None')
should_end_session = False
if 'object' in intent['slots'] and 'value' in intent['slots']['object']:
obj = intent['slots']['object']['value']
room = session_attributes['room']
if is_object_in_room(room, obj) or is_object_in_inventory(session_attributes['inventory'], obj):
speech_output = use_object_in_room(intent, session, obj, room)
else:
speech_output = "I can not find " + obj + " here."
reprompt_text = "You can use all objects in the room you are in."
else:
speech_output = "I'm not sure what you want to use. " \
"Please try again."
reprompt_text = "I'm not sure what you want to use. " \
"You can use all objects in the room you are in by saying, " \
"use, plus the objects name?"
return build_response(session_attributes, build_speechlet_response(
'Use', speech_output, reprompt_text, should_end_session))Complete list of actions to complete the game.
def inventory(intent, session):
session_attributes = session['attributes']
if 'value' in intent['slots']['status']:
event_counter(intent, session_attributes, "inventory", intent['slots']['status']['value'])
else:
event_counter(intent, session_attributes, "inventory", 'None')
should_end_session = False
#if 'status' in intent['slots']:
#status = intent['slots']['status']['value']
#if status == 'open':
speech_output = "I have a "
inventory = session_attributes['inventory']
for obj in inventory[:-1]:
speech_output += obj + " "
if len(inventory) > 1:
speech_output += "and " + inventory[-1:][0]
else:
speech_output += inventory[-1:][0]
speech_output = speech_output + "."
reprompt_text = speech_output
return build_response(session_attributes, build_speechlet_response(
'Inventory', speech_output, reprompt_text, should_end_session))
def combine(intent, session):
session_attributes = session['attributes']
should_end_session = False
speech_output = "Please tell me which objects you like to combine."
reprompt_text = "Please tell me which objects you like to combine."
if 'objectone' in intent['slots'] and 'objecttwo' in intent['slots'] and 'value' in intent['slots']['objectone'] and 'value' in intent['slots']['objectone']:
objectone = intent['slots']['objectone']['value']
objecttwo = intent['slots']['objecttwo']['value']
#TODO Sort combine values nach alphabet damit das event eindeutig ist
event_speech = event_counter(intent, session_attributes, "combine", objectone + "_" + objecttwo)
if event_speech == "":
speech_output = "I can not combind " + objectone + " with " + objecttwo + "."
reprompt_text = "I'm not sure how to combind " + objectone + " with " + objecttComplete list of actions to complete the game.wo + "."
else:
speech_output = event_speech
reprompt_text = event_speech
if (is_object_in_room(session_attributes['room'], objectone) \
or is_object_in_inventory(session_attributes['inventory'], objectone)) \
and (is_object_in_room(session_attributes['room'], objecttwo) \
or is_object_in_inventory(session_attributes['inventory'], objecttwo)):
for combination in combinations['combinations']:
if objectone in combination['in'] and objecttwo in combination['in']:
session_attributes['inventory'].remove(objectone)
session_attributes['inventory'].remove(objecttwo)
session_attributes['inventory'].append(combination['out'])
speech_output = "I now have " + combination['out'] + "."
reprompt_text = "I now have " + combination['out'] + "."
return build_response(session_attributes, build_speechlet_response(
'Combine', speech_output, reprompt_text, should_end_session))
# --------------- Helpers that build all of the responses ----------------------
def build_speechlet_response(title, output, reprompt_text, should_end_session):
return {
'outputSpeech': {
'type': 'PlainText',
'text': output
},
'card': {
'type': 'Simple',
'title': title,Complete list of actions to complete the game.
'content': output
},
'reprompt': {
'outputSpeech': {
'type': 'PlainText',
'text': reprompt_text
}
},
'shouldEndSession': should_end_session
}
def build_response(session_attributes, speechlet_response):
return {
'version': '1.0',
'sessionAttributes': session_attributes,
'response': speechlet_response
}
# -----------------------------Test --------------------------------------------
def test():
#Custom Slot Types
print("OBJECTS")
for obj in objects["objects"]:
print (obj["name"])
print ("")
print ("ROOMS")
for room in rooms["rooms"]:
print (room["name"])
print("") #Only 'open' as an INVENTORYSTATUS
print("INVENTORYSTATUS")
print("open")
if __name__ == "__main__":
test()
Comments