Who's Who
Who's Who is our version of the classic Whodunnit game. You a represented with a list of people and you must identify the suspect by asking questions about them. But our game doesn't stop there, once you have identified the suspect, you must then pick them out of a line up by recognising an alternative image of them.
This game is an excellent introduction to using Microsoft's Vision and Text APIs.
Your calculate_move() function will be passed the current state of the game, the 'gamestate'. The gamestate is a python dictionary containing the following keys:
- ImageGrids - A list of strings containing the URLs of images that contain the faces and names of the characters of this game. Each image will be a grid of multiple faces and there may be more than one URL string per game.
- RemainingCharacters - A list of integers representing which characters (suspects) from the original images are still active in the game (i.e. have not been eliminated by asking questions).
- OpponentCharacters - A list of integers representing which of your opponent's characters from the original images are still active in the game (i.e. have not been eliminated by asking questions).
- RemainingQuestions - A list of Key, Pair values containing all questions that are still valid to be asked. For example:
[['Hair', 'Blond'], ['Hair', 'Black'], ['Hair', 'Brown'], ['Hair', 'Red'], ['Hair', 'Gray'], ['Hair', 'Bald'], ['Hair', 'Invisible'], ['Hair', 'Other'], ['Accessories', 'HeadWear'], ['Glasses', 'NoGlasses'], ['Glasses', 'Sunglasses'], ['Glasses', 'ReadingGlasses'], ['Glasses', 'SwimmingGoggles'], ['Gender', 'Male'], ['Gender', 'Female'], ['Emotion', 'Happiness'], ['Emotion', 'Sadness'], ['Emotion', 'Neutral'], ['Emotion', 'Surprise'], ['Name', 'Start'], ['Name', 'End'], ['Name', 'Contain'], ['Name', 'Is'], ['Age'], ['FacialHair'], ['Smile']]
- IsMover - A boolean stating if the server is waiting for you to make a move.
- Round - A string identifying the current round type for this move. Values will be either "CHOOSE CHARACTER", "QUESTIONS" or "GUESS OPPONENT".
- ResponseDeadline - The epoch time, in milliseconds, by which a successful move has to be sent and received to prevent you from timing out.
- GameStatus - A string that will have value "RUNNING" if the game is in progress or a reason the game has ended otherwise.
- GameId - An integer representing the unique game id for the current game.
- OpponentId - A string containing the name of your opponent.
- MyCharacterImage - The character image that you guessed in the previous round
- ComparisonImages - List of URLs of images of characters in the line up for Guess Opponent round.
The characters (suspects) in the game are provided to you in grids of images. You receive a list of strings that contain the URLs of these image grids. You may receive more than one image grid. An example grid is shown below:

There are two game styles that we may play at the hackathon - a 16 face game that will include only one grid of images, and a 32 face game that will include two. The Microsoft Face Detection need only be called once to return all 16 faces from a single grid of images, and you can see this working in the demo code in the Online Code Editor.
Using the Microsoft Cognitive API, you will be able to identify the location of each face and the attributes of each face, like, black hair or reading glasses or hat, as well as the name of the character, read from the label underneath each face.
We suggest you use the following Cognitive Services APIs:
Images are referred to during the game by their index and so you need to interpret the index number of each character. The Microsoft API helps you significantly in this process as it identifies the location of each face it finds.
The index numbers for each image are calculated from left to right top to bottom as shown in the image below. If there are multiple image grids, the index numbers continue from one image to the next, e.g. 16, 17, 18 etc. The example below shows the index of the of each person when you play a game with sixteen characters:

The value you have to return from the calculate_move() function varies depending upon which round of the game you are in. The rounds are:
- CHOOSE CHARACTER
- QUESTIONS
- GUESS OPPONENT
This is where you select the character that you want your opponent to guess. Choosing a hard to guess opponent increases the difficulty for your opponent.
To submit the character you want your opponent to guess in the Choose Character round, you must return a key, value pair with the index number of the character you want to select as the value.
return {"MyCharacter": 0}
This round is where you ask questions to eliminate characters as you try to determine which character your opponent set as the suspect.
To submit questions, you return a list of Questions as Key, Pair values. You can submit 1 or more questions at the same time.
return {"Questions": [["Hair": "Black"]]}
Some attributes (Smile and FacialHair) are true/false, and you do not need to specify which (you will be returned a list of remaining suspects based on which have the same value for that attribute as the correct suspect):
return {"Questions": [["Smile"]] }
For age, you can specify a range by adding the minimum and maximum age:
return {"Questions": [["Age", 20, 30 ]] }
You can narrow the list of suspects by guessing parts of their names. You send a string of "Name" followed by a comparator ("Is", "Start", "End", "Contains"), then the value. Comparisons are not case sensitive. For example:
return {"Questions": [["Name", "Start", "Paul M"]] }
Whether your guess was right or wrong, the return value from the server shows the remaining suspects.
For example, if you guessed that the suspect's hair was black and this was true, you will be returned a list of remaining suspects with only black hair. If the correct suspect does not have black hair, you will be returned a list of remaining suspects with only non-black hair.
You can ask multiple questions at once by submitting the questions in a list. For example:
return {"Questions":
["Hair": "Black"],
["Glasses": "SwimmingGoggles"]}
If you ask two questions at once, you are effectively asking if the correct suspect has one property AND the other. For example, if you ask if the correct suspect's hair is black and if they are wearing swimming goggles you will receive one of these two responses:
1. If the correct suspect has both black hair and is wearing swimming goggles, you will receive a list of remaining suspects that have both black hair and are wearing swimming goggles.
2. If the correct suspect either does not have black hair OR is not wearing swimming goggles, you will receive back a list of remaining suspects which have either non-black hair OR are not wearing swimming goggles.
If you ask a true/false question (e.g. "Smile") in a list of questions, we assume you are asking the positive. E.g. is the person both male AND smiling.
This round is where you have to identify the correctly guessed suspect in a line up. You have received a list of images and you have to identify the image that matches your chosen suspect.
We suggest you use the:
To submit your lineup answer, you return a Key, Pair value where the value is the index of the image you think matches.
return {"OppCharacter": 4}
Given the result from the Computer Vision OCR API appends the character names to currentList in index order
listNames(nameData, currentList)
Given the result from the Face API appends the face attributes of the characters to currentList in index order
listFaces(faceData, currentList)
Given the comparison image urls, and the image they should be compared against, returns the characters in order of similarity
listComparisons(comparisonImages, MyCharacterImage)
- Epoch time - The number of seconds (or in our case milliseconds) that have elapsed since January 1 1970 00:00 UTC.
Last modified 3yr ago