wordle/app.py

162 lines
4.9 KiB
Python
Raw Normal View History

2022-01-18 21:52:14 +01:00
import random
from string import ascii_lowercase
from flask import Flask, render_template, session, request, redirect, url_for, flash
import sensitive
2022-01-18 23:01:23 +01:00
from lib import cat_words, ROUNDS, WORD_LENGTH
2022-01-18 21:52:14 +01:00
from play import build_non_letter_hint, build_letter_hint
app = Flask(__name__)
app.config['SECRET_KEY'] = sensitive.SECRET_KEY
2022-01-18 23:01:23 +01:00
2022-01-18 22:42:38 +01:00
WORDS = list(cat_words())
NUM_GAMES = len(WORDS) - 1
2022-01-18 21:52:14 +01:00
GUESS_SPLITTER = '|'
2022-01-18 23:01:23 +01:00
RANDOM_GAME_ID = -1
KEY_WORD = 'word'
KEY_GAME_ID = 'game_id'
KEY_GUESSES = 'guesses'
KEY_GUESS = 'guess'
KEY_STATE = 'state'
2022-01-18 21:52:14 +01:00
STATE_PLAYING = 'PLAYING'
STATE_WIN = 'WIN'
STATE_LOSE = 'LOSE'
2022-01-18 23:01:23 +01:00
COLOR_GREY = 'grey'
COLOR_GREEN = 'green'
COLOR_YELLOW = 'yellow'
ERROR_GAME_ID_RANGE = "game_id must be between 0 and {}".format(NUM_GAMES)
ERROR_NEED_WORD = 'need a word'
ERROR_GUESS_LENGTH = "Make a {} letter guess.".format(WORD_LENGTH)
ERROR_WORD_NOT_IN_LIST = 'Not in word list: {}'
ERROR_NO_GAME = 'No game started.'
2022-01-18 21:52:14 +01:00
2022-01-18 22:33:49 +01:00
def init_game(game_id, word):
2022-01-18 23:01:23 +01:00
session[KEY_GAME_ID] = game_id
session[KEY_WORD] = word
session[KEY_GUESSES] = ''
session[KEY_STATE] = STATE_PLAYING
2022-01-18 21:52:14 +01:00
def resolve_guesses():
2022-01-18 23:01:23 +01:00
word = session[KEY_WORD]
guesses = session.get(KEY_GUESSES, '').split(GUESS_SPLITTER)
2022-01-18 21:52:14 +01:00
guesses_colored = []
for guess in guesses:
non_letters_hints = build_non_letter_hint(guess, word)
letters_hints = build_letter_hint(guess, word)
colored_guess = []
for pos, letter in enumerate(guess):
if letter in non_letters_hints:
2022-01-18 23:01:23 +01:00
color = COLOR_GREY
2022-01-18 21:52:14 +01:00
elif letters_hints[pos] == letter.upper():
2022-01-18 23:01:23 +01:00
color = COLOR_GREEN
2022-01-18 21:52:14 +01:00
elif letters_hints[pos] == letter:
2022-01-18 23:01:23 +01:00
color = COLOR_YELLOW
2022-01-18 21:52:14 +01:00
else:
2022-01-18 23:01:23 +01:00
color = COLOR_GREY
2022-01-18 21:52:14 +01:00
colored_guess.append((letter, color))
guesses_colored.append(colored_guess)
return guesses_colored
def build_game_state():
guesses_colored = resolve_guesses()
return render_template('game.html',
guesses=guesses_colored,
2022-01-18 23:01:23 +01:00
state_playing=session[KEY_STATE] == STATE_PLAYING,
WORD_LENGTH=WORD_LENGTH,
KEY_GUESS=KEY_GUESS,
state=session[KEY_STATE])
# #############################################################################
# ROUTES
# #############################################################################
2022-01-18 21:52:14 +01:00
2022-01-18 22:42:38 +01:00
@app.route('/')
def home():
num_games = NUM_GAMES
2022-01-18 23:01:23 +01:00
return render_template('home.html', num_games=num_games, KEY_GAME_ID=KEY_GAME_ID)
2022-01-18 22:42:38 +01:00
@app.route('/init/random')
def init_random_game():
word = random.choice(WORDS)
init_game(RANDOM_GAME_ID, word)
return redirect(url_for('random_game'))
@app.route('/init/deterministic', methods=['post'])
def init_deterministic_game():
2022-01-18 23:01:23 +01:00
game_id = request.form.get(KEY_GAME_ID)
2022-01-18 22:42:38 +01:00
return redirect(url_for('init_deterministic_game_id', game_id=game_id))
@app.route('/init/deterministic/<int:game_id>')
def init_deterministic_game_id(game_id):
if not 0 <= int(game_id) <= NUM_GAMES:
2022-01-18 23:01:23 +01:00
flash(ERROR_GAME_ID_RANGE)
2022-01-18 22:42:38 +01:00
return redirect(url_for('home'))
word = WORDS[int(game_id)]
init_game(game_id, word)
return redirect(url_for('deterministic_game_id', game_id=game_id))
2022-01-18 21:52:14 +01:00
@app.route('/random')
def random_game():
2022-01-18 23:01:23 +01:00
if KEY_WORD not in session or KEY_STATE not in session:
2022-01-18 21:52:14 +01:00
return redirect(url_for('init_random_game'))
return build_game_state()
@app.route('/deterministic/<int:game_id>')
def deterministic_game_id(game_id):
2022-01-18 23:01:23 +01:00
if (KEY_WORD not in session or KEY_STATE not in session or
(KEY_GAME_ID in session and session[KEY_GAME_ID] != game_id)):
2022-01-18 21:52:14 +01:00
return redirect(url_for('init_deterministic_game_id', game_id=game_id))
return build_game_state()
@app.route('/guess', methods=['post'])
def make_guess():
2022-01-18 23:01:23 +01:00
if KEY_WORD not in session or KEY_GUESSES not in session:
flash(ERROR_NEED_WORD)
2022-01-18 21:52:14 +01:00
return redirect(url_for('home'))
2022-01-18 23:01:23 +01:00
guess = request.form.get(KEY_GUESS)
2022-01-18 22:33:49 +01:00
guess = guess.lower()
2022-01-18 23:01:23 +01:00
if len(guess) != WORD_LENGTH and not all([x in ascii_lowercase for x in guess]):
flash(ERROR_GUESS_LENGTH)
return build_game_state()
2022-01-18 22:42:38 +01:00
if guess not in WORDS:
2022-01-18 23:01:23 +01:00
flash(ERROR_WORD_NOT_IN_LIST.format(guess))
2022-01-18 21:52:14 +01:00
return build_game_state()
2022-01-18 23:01:23 +01:00
word = session[KEY_WORD]
round_i = len(session[KEY_GUESSES].split(GUESS_SPLITTER))
if round_i >= ROUNDS:
session[KEY_STATE] = STATE_LOSE
2022-01-18 21:52:14 +01:00
if guess == word:
2022-01-18 23:01:23 +01:00
session[KEY_STATE] = STATE_WIN
session[KEY_GUESSES] += '{}{}'.format(guess, GUESS_SPLITTER)
if KEY_GAME_ID not in session:
flash(ERROR_NO_GAME)
2022-01-18 21:52:14 +01:00
return redirect(url_for('home'))
2022-01-18 23:01:23 +01:00
game_id = session[KEY_GAME_ID]
if game_id == RANDOM_GAME_ID:
2022-01-18 21:52:14 +01:00
return redirect(url_for('random_game'))
return redirect(url_for('deterministic_game_id', game_id=game_id))
def main():
app.run(debug=True)
if __name__ == "__main__":
main()