This is an old one I did using Python (in Google App Engine). When you opt in by sending "Play" to the Twilio number, you are given a name of a person. You want to do everything you can to get others to guess this person, besides saying their name. Those who have played Catch Phrase will understand this concept. The goal of this game is to get the most points. You gain points by both guessing people (10) and by being guessed (20). Text "pass" to chance your character; text "reset" to reset the game. The first person to 200 points wins.

Here's the initial setup for this GAE project.
[python title="app.yaml"]
application: idovoices
version: 1
runtime: python
api_version: 1

handlers:
- url: /sms
script: sms.py
[/python]

When guesses are made, they are given a little bit of leniency, allowing people to guess spellings of names, and if its close enough still give them the points. This comparison is called the Levenshtein Distance.
[python title="levenshtein.py"]
def levenshtein(s1, s2):
if len(s1) < len(s2):
return levenshtein(s2, s1)
if not s1:
return len(s2)

previous_row = xrange(len(s2) + 1)
for i, c1 in enumerate(s1):
current_row = [i + 1]
for j, c2 in enumerate(s2):
insertions = previous_row[j + 1] + 1 # j+1 instead of j since previous_row and current_row are one character longer
deletions = current_row[j] + 1 # than s2
substitutions = previous_row[j] + (c1 != c2)
current_row.append(min(insertions, deletions, substitutions))
previous_row = current_row

return previous_row[-1]
[/python]

This is probably my most complex GAE project, which stores both word and user models in the appengine db. They keep track of people's scores and how often a word is used.

[python title="User.py"]
from google.appengine.ext import db

class User(db.Model):
number = db.PhoneNumberProperty()
score = db.IntegerProperty(default=0)
word = db.StringProperty(verbose_name=None, multiline=False)
[/python]
[python title="Word.py"]
from google.appengine.ext import db

class Word(db.Model):
name = db.StringProperty(verbose_name=None, multiline=False)
lastUse = db.DateTimeProperty(auto_now=True)
[/python]

When the system receives text messages, they are handled by sms.py. This file loads a bunch of others, including Word and User. It also imports the twilio library for sending texts, and words.py for generating names to assign to users.

[python title="sms.py"]
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import re

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext import db
from words import getWords
import twilio
import User
import Word
from levenshtein import levenshtein

GUESS_THRESHOLD = 3
CORRECT_GUESS = 10
NAME_GUESSED = 20
MAX_SCORE = 200

class MainHandler(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello sms!<br>')
query = self.request.query_string
self.response.out.write("GET Query: " + query + "<br>")
self.response.out.write("GET Body: " + self.request.body + "<br>")
return

def post(self):
phoneNumber = self.request.get("From", "NONUMBER")
body = self.request.get("Body", "NOBODY")

argumentsList = self.request.arguments()

for argument in argumentsList:
logging.info("arg " + argument + " " + self.request.get(argument) + "n")

logging.info("Body: " + body + "n")

# New player
if(body.lower()=="play"):
logging.info("addNumber: " + phoneNumber) # Debug purposes
newNumber(phoneNumber)

sendText("Welcome! Your first character is: " + assignNextName(phoneNumber), self)
return

# PASS
if(body.lower()=="pass"):
logging.info("phoneNumber: " + phoneNumber) # Debug purposes

sendText("Skipped! Next character: " + assignNextName(phoneNumber), self)
return

# RESET
if(body.lower()=="reset"):
logging.info("reset: " + phoneNumber) # Debug purposes
resetGame()
sendText("Game reset", self)
return

# NAME
submitGuess(phoneNumber, body, self)

def newNumber(phoneNumber):
logging.info("New number: " + phoneNumber)
user = User.User(number = phoneNumber, score=0)

deleteNumber(phoneNumber)
user.put()
return user

def assignNextName(phoneNumber):
# Search the database for the next item
nextWord = Word.Word.gql("ORDER BY lastUse ASC LIMIT 1")

# if the database is empty, rerun the immport
if(nextWord.count()==0):
importWords()
nextWord = Word.Word.gql("ORDER BY lastUse ASC LIMIT 1")
nextName = nextWord[0].name
nextWord[0].put() #touch the object to reset the timestamp
# Update the User object for number
user = getUser(phoneNumber)
user.word = nextName
user.put()
# Return the string
return nextName

def deleteNumber(phoneNumber):
logging.info("Delete number: " + phoneNumber)
previousUser = getUser(phoneNumber)
if(previousUser):
previousUser.delete()

def getUser(phoneNumber):
storedUsers = User.User.gql("WHERE number = :1", phoneNumber)
if(storedUsers.count()!=0):
return storedUsers[0]
else:
return 0

def submitGuess(phoneNumber, guess, self):
currentPlayers = User.User.gql("")
# for each current person in the db
logging.info("Guess is " + guess)
for player in currentPlayers:
logging.info("player number " + str(player.number))
if(player.number == phoneNumber or not player.word):
continue
distance = levenshtein(guess.lower(), player.word.lower())
logging.info("distance: " + str(distance))
if(distance <= GUESS_THRESHOLD):
r = twilio.Response()
# Award points
guesserScore = addPoints(phoneNumber, CORRECT_GUESS)

guesserMessage = "You guessed " + player.word + " correct! Your score is now "+ str(guesserScore) + "."
if(guesserScore >= MAX_SCORE):
guesserMessage += " You win!"
r.addSms(guesserMessage, to=phoneNumber)

guessedScore = addPoints(player.number, NAME_GUESSED)
guessedMessage = "You were guessed! Score: " + str(guessedScore) + "."
if(guessedScore >= MAX_SCORE):
guessedMessage += " You win!"
else:
guessedMessage += " Next: " + assignNextName(player.number)
r.addSms(guessedMessage, to=player.number)
self.response.out.write(r)
if(guesserScore >= MAX_SCORE or guessedScore >= MAX_SCORE):
resetGame()
return player.word

def addPoints(phoneNumber, amount):
# Update the User object for number
user = getUser(phoneNumber)
if(user==0):
user = newNumber(phoneNumber)
user.score += amount
user.put()

# Return the string
return user.score

def sendText(message, self):
r = twilio.Response()
r.addSms(message)
self.response.out.write(r)

def importWords():
for word in getWords():
dbWord = Word.Word()
dbWord.name = word
dbWord.put()

def resetGame():
logging.info("resetting!")
db.delete(User.User.gql(""))

def main():
application = webapp.WSGIApplication([('/sms', MainHandler)],
debug=True)
util.run_wsgi_app(application)

if __name__ == '__main__':
main()
[/python]

To try it out,

  1. clone the project on Github, modify the app.yaml application to your own.
  2. Use Google App Engine to deploy the project.
  3. Set a Twilio phone number's SMS to POST to /sms on your project URL.
  4. Text "play" to your Twilio number.
  5. Text your guesses to the same number.