Wordle-Variant / client
client
Raw
#!/usr/bin/env python3

import argparse
import traceback
import socket
import ssl
import sys
import re
import json
import random

wordlist = []

# First, store the wordlist for guessing
with open('words.txt','r') as file:
    # read each line    
    for line in file:
        # read each word        
        for word in line.split():
            # append the words      
            wordlist.append(word)

notInWord = []
inWord = []
inPlace = ['']*5

def attempt_guess(id, guesses):
    if guesses is not None:
        for i in range(0, 5):
            if (guesses['marks'][i] == 0):
                notInWord.append(guesses['word'][i])
            elif (guesses['marks'][i] == 1):
                inWord.append(guesses['word'][i])
            elif (guesses['marks'][i] == 2):
                inPlace[i] = guesses['word'][i]
            else:
                raise Exception('Invalid mark')
    guess = ''
    while guess == '':
        guess = random.choice(wordlist)
        wordlist.remove(guess)
        for c in notInWord:
            if c in guess:
                guess = ''
                break
        for c in inWord:
            if c not in guess:
                guess = ''
                break
        if guess == '':
            continue
        for i in range(len(inPlace)):
            if inPlace[i] != '' and guess[i] != inPlace[i]:
                guess = ''
                break

    guess_message = {'type': 'guess', 'id': id, 'word': guess}
    return guess_message

def get_flag(sockt, username):
    hello = {'type': 'hello', 'northeastern_username': username} # C -> S interaction
    sockt.sendall((json.dumps(hello) + '\n').encode('ascii'))

    # Keeps asking for guesses of the word
    while True:
        # Processes the entire line
        data = sockt.recv(10000).decode('ascii')
        while not data.endswith('\n'):
            data += sockt.recv(10000).decode('ascii')
        message = json.loads(data)

        if re.match('start', message['type']):
            id = message['id']
            sockt.sendall((json.dumps(attempt_guess(id, None)) + '\n').encode('ascii'))
        elif re.match('retry', message['type']): # C -> S interaction
            sockt.sendall((json.dumps(attempt_guess(id, message['guesses'][-1])) + '\n').encode('ascii'))
        elif re.match('bye', message['type']):
            return message['flag']
        else:
            raise Exception('Could not understand message: {}'.format(message))

if __name__ == '__main__':
    # Start to parse necessary arguments 
    parser = argparse.ArgumentParser(usage='./client <-p port> <-s> <hostname> <Northeastern-username>')
    parser.add_argument('-p', type=int, help='optional TCP port', required = False, dest = 'port')
    parser.add_argument('-s', action='store_true', 
                        help='determines whether or not to use TLS encrypted socket', 
                        required = False, dest='use_tls')
    parser.add_argument('hostname', type=str, help='name of the server', nargs='?', default='proj1.3700.network')
    parser.add_argument('Northeastern_username', type=str, help = 'Northeastern username', nargs='?', default='zinger.m')
    
    args = parser.parse_args()

    sockt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if args.use_tls:
        sockt = ssl.wrap_socket(sockt)

    # Here, we use the given port if specified, 
    # otherwise, assume the port is 27993
    # but if given -s flag, we use TLS encryption
    # and assume port is 27994
    port = args.port if args.port is not None else (
        27994 if args.use_tls else 27993)

    try:
        sockt.connect((args.hostname, port))
    except socket.error as error_message:
        print('Could not connect to server: {}'.format(error_message))
        sys.exit(1)

    try:
        flag = get_flag(sockt, args.Northeastern_username)
        sockt.close()
    except Exception as error_message:
        print(traceback.format_exc())
        print('Could not retrieve secret flag: {}'.format(error_message))
        sys.exit(1)

print(flag)