PHP Classes

File: wordle-cli

Recommend this page to a friend!
  Classes of Rodolfo Berrios Arce   Wordle CLI   wordle-cli   Download  
File: wordle-cli
Role: Example script
Content type: text/plain
Description: Example script
Class: Wordle CLI
Run the Wordle game on the command line console
Author: By
Last change:
Date: 26 days ago
Size: 6,100 bytes
 

Contents

Class file image Download
#!/usr/bin/env php
<?php

/*
 * This file is part of Chevere.
 *
 * (c) Rodolfo Berrios <[email protected]>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

declare(strict_types=1);

use
League\CLImate\CLImate;
use
Rodber\Wordle\Compare;
use
Rodber\Wordle\Word;
use function
Chevere\Filesystem\filePhpReturnForPath;

require_once
__DIR__ . '/vendor/autoload.php';

$climate = new CLImate();
$climate->clear();
$climate->addArt(__DIR__ . '/app/banner');
$climate->animation('intro')->speed(200)->enterFrom('top');

$options = [
   
'en' => 'English',
   
'es' => 'Español',
   
'pt' => 'Português',
];
$input = $climate->radio('Language selection:', $options);
$lang = $input->prompt();

$climate->addArt(__DIR__ . "/app/lang/{$lang}/banner");

$en = [
   
'options' => 'Game options',
   
'length' => 'Word length [3, 8] (default 5)',
   
'responses' => 'Responses [0, n] (default 6, no limit 0)',
   
'looking' => 'Looking for <invert> %length% </invert> char word',
   
'try' => 'Try',
   
'must' => 'Word must be %s char length',
   
'unknown' => 'Unknown word (not in wordlist)',
   
'welcome' => 'Welcome to Wordle CLI!',
   
'instructions' => 'You have to guess a word of a certain length.',
   
'exact_match' => 'Exact match',
   
'partial_match' => 'Partial (wrong position)',
   
'no_match' => 'No match',
   
'tries' => 'tries',
];

$es = [
   
'options' => 'Opciones del juego',
   
'length' => 'Largo de palabra [3, 8] (defecto 5)',
   
'responses' => 'Respuestas [0, n] (defecto 6, sin límite 0)',
   
'looking' => 'Buscando palabra de <invert> %length% </invert> caracteres',
   
'try' => 'Intento',
   
'must' => 'La palabra debe ser de %s caracteres',
   
'unknown' => 'Palabra desconocida (no está en el diccionario)',
   
'welcome' => 'Bienvenido a Wordle CLI!',
   
'instructions' => 'Tienes que adivinar una palabra de cierta longitud.',
   
'exact_match' => 'Coincidencia exacta',
   
'partial_match' => 'Parcial (posición incorrecta)',
   
'no_match' => 'Sin coincidencia',
   
'tries' => 'intentos',
];

$pt = [
   
'options' => 'Opções do jogo',
   
'length' => 'Comprimento da palavra [3, 8] (padrão 5)',
   
'responses' => 'Respostas [0, n] (padrão 6, sem limite 0)',
   
'looking' => 'Procurando palavra de <invert> %length% </invert> caracteres',
   
'try' => 'Tente',
   
'must' => 'A palavra deve ter %s caracteres',
   
'unknown' => 'Palavra desconhecida (não está no dicionário)',
   
'welcome' => 'Bem-vindo ao Wordle CLI!',
   
'instructions' => 'Você tem que adivinhar uma palavra de certo comprimento.',
   
'exact_match' => 'Correspondência exata',
   
'partial_match' => 'Parcial (posição errada)',
   
'no_match' => 'Sem correspondência',
   
'tries' => 'tentativas',
];

$LANG = $$lang;

$climate->br()->out('? ' . $LANG['welcome'])->br();
$climate->out($LANG['instructions'])->br();
$climate->out('? ' . $LANG['exact_match']);
$climate->out('? ' . $LANG['partial_match']);
$climate->out('? ' . $LANG['no_match'])->br();

$options = range(3, 8);
$climate->out('<green>' . $LANG['options'] . '</green>');
$input = $climate->input('<green>* ' . $LANG['length'] . ':</green>');
$input->defaultTo('5');
$input->accept($options);
$wordLength = intval($input->prompt());

$input = $climate->input('<green>* ' . $LANG['responses'] .' :</green>');
$input->defaultTo('6');
$ansTries = intval($input->prompt());
$attempts = $ansTries === 0
   
? '?'
   
: $ansTries;

$wordListFile = filePhpReturnForPath(__DIR__ . "/app/lang/{$lang}/words/{$wordLength}.php");
$wordList = $wordListFile->cast()->array();
$randomWord = mb_strtoupper($wordList[rand(0, count($wordList))]);
$word = new Word($randomWord);
$climate->br()->out(
   
strtr(
       
'? ' . $LANG['looking'] . ':',
        [
           
'%length%' => $wordLength,
        ]
    )
)->
br();
$emojiLines = [];
$answers = [];
$try = 0;
do {
   
$input = $climate->input(
       
strtr('? '. $LANG['try'] .' %try/%attempts:', [
           
'%try' => strval($try + 1),
           
'%attempts' => $attempts,
        ])
    );
   
$ansTries = $input->prompt();
    if (
strlen($ansTries) === 0) {
       
$noMatch = true;
       
$climate->error(
           
sprintf($LANG['must'], $word->length())
        );

        continue;
    }
   
$attemptUpper = mb_strtoupper($ansTries);
   
$attemptLower = mb_strtolower($ansTries);
   
$against = new Word($attemptUpper);
    if (
$against->length() !== $word->length()) {
       
$noMatch = true;
       
$climate->error(
           
sprintf($LANG['must'], $word->length())
        );

        continue;
    }
    if (!
in_array($attemptLower, $wordList, true)) {
       
$noMatch = true;
       
$climate->error($LANG['unknown']);

        continue;
    }
   
$answers[] = $attemptUpper;
   
$compare = new Compare($word, $against);
   
$noMatch = ! $compare->match();
   
$explain = [];
   
$emoji = '';
    foreach (
$against->split() as $pos => $letter) {
       
$match = $compare->computed()[$pos][$letter];
       
$color = '' . match ($match) {
           
Word::CHAR_MATCH_EXACT => 'green',
           
Word::CHAR_MATCH_PARTIAL => 'light_yellow',
           
Word::CHAR_MATCH_NONE => 'dark_gray',
        };
       
$explain[] = "<invert><{$color}> {$letter} </{$color}></invert>";
       
$emoji .= match ($match) {
           
Word::CHAR_MATCH_EXACT => '?',
           
Word::CHAR_MATCH_PARTIAL => '?',
           
Word::CHAR_MATCH_NONE => '?',
        };
    }
   
$emojiLines[] = $emoji;
   
$explain[] = ' <invert><green>(' . $compare->fraction() . ')</green></invert>';
   
$climate->out(implode('', $explain));
   
$try++;
} while (
$noMatch && ($attempts !== '?' && $try < $attempts));
$climate->animation($noMatch ? 'lose' : 'win')->enterFrom('bottom');
$LANGdgame = strtr('%icon% GAME OVER (%tries% ' . $LANG['tries'] . ') ? %word%', [
   
'%tries%' => $try,
   
'%icon%' => $noMatch ? '?' : '?',
   
'%word%' => $randomWord,
]);
$climate->flank($LANGdgame, '*', 3);
$climate->br()->out(implode("\n", $emojiLines));