pull/61/merge^2
Daniel Kunkler 2022-01-27 18:05:14 -06:00
commit 666fd89421
7 zmienionych plików z 110 dodań i 15 usunięć

Wyświetl plik

@ -1,27 +1,41 @@
# hello wordl
It's [Wordle](https://www.powerlanguage.co.uk/wordle/) but you can play forever!
Play it [**here**](https://hellowordl.net/).
## Introduction
Wordle is a word game similar to the TV show [Lingo](https://en.wikipedia.org/wiki/Lingo_(British_game_show)).
Wordle is a word game similar to the TV show [Lingo](<https://en.wikipedia.org/wiki/Lingo_(British_game_show)>).
You get 6 tries to guess a 5-letter target word. After each guess, the letters light up in various colors as clues. Green means a letter is correct in this spot; yellow means a letter is _elsewhere_ in the target word; gray means a letter is not in the target word at all.
Click _About_ inside the game to learn by example.
## History
In 2021, Josh "powerlanguage" Wardle created _Wordle_, a version of the Lingo word game that you can play once a day. The target word is the same for everyone each day, and you can share results to Twitter and compare with your friends. This made Wordle [go absolutely viral](https://www.nytimes.com/2022/01/03/technology/wordle-word-game-creator.html) around January 2022.
I liked this game a lot, but wanted to play more than once a day, so I created my own version of it, where the words are random but you can play as much as like. I called it _hello wordl_, which is a sort of [bad programming joke](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program).
## But playing once a day is the point!
Don't get me wrong: I, too, think this is the most brilliant aspect of Wordle, and I don't aim to dethrone or improve on the "real" game.
## My word contained two of the same letter!
This can happen in Wordle too, and I give clues exactly the same way Wordle does. I think the game would be too easy if I got rid of double letters, so I won't.
## Where are the words coming from?
To generate target words, I have been manually curating the top 25,000 or so entries of [Peter Norvig's English word frequency list](http://norvig.com/mayzner.html) to get rid of obscure words, plurals, conjugated verbs, inappropriate language, and British spellings (sorry). If you get dealt a strange target word, please open an issue on this here GitHub repository.
To check guesses, I use some variation of the _Official Tournament and Club Word List_ used in North American Scrabble tournaments. (I'm not a native English speaker, but my English tends mostly American.)
## For developers
You're very welcome to create your own Wordle offshoot/remix based on _hello wordl_. To get started, you can [fork the code](https://docs.github.com/en/get-started/quickstart/fork-a-repo) on GitHub.
To run the code locally, first install [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm#using-a-node-version-manager-to-install-nodejs-and-npm). Then, in this directory, open a terminal and run `npm install` followed by `npm run start`. _hello wordl_ will be running at http://localhost:3000/. Any changes you make to the source code will be reflected there. Have fun!
Finally, `npm run deploy` will deploy your code to the `gh-pages` branch of your fork, so that everyone can play your version at https://yourname.github.io/hello-wordl (or the name of your fork if you renamed it).

Wyświetl plik

@ -33,13 +33,13 @@ export function About() {
<b>W</b> and <b>O</b> aren't in the target word at all.
</p>
<p>
<b className="green-bg">R</b> is correct! The third letter is{" "}
<b className="green-bg">R</b>
<b className={"green-bg"}>R</b> is correct! The third letter is{" "}
<b className={"green-bg"}>R</b>
.<br />
<strong>(There may still be a second R in the word.)</strong>
</p>
<p>
<b className="yellow-bg">D</b> occurs <em>elsewhere</em> in the target
<b className={"yellow-bg"}>D</b> occurs <em>elsewhere</em> in the target
word.
<br />
<strong>(Perhaps more than once. 🤔)</strong>
@ -78,7 +78,8 @@ export function About() {
<p>
This game will be free and ad-free forever,
<br />
but you can <a href="https://ko-fi.com/chordbug">buy me a coffee</a> if you'd like.
but you can <a href="https://ko-fi.com/chordbug">buy me a coffee</a> if
you'd like.
</p>
</div>
);

Wyświetl plik

@ -26,6 +26,19 @@ body {
text-transform: uppercase;
font-weight: bold;
}
.Row-letter-color {
margin: 2px;
border: 2px solid rgba(128, 128, 128, 0.8);
flex: 1;
max-width: 40px;
height: 40px;
font-size: 28px;
display: flex;
justify-content: center;
align-items: center;
text-transform: uppercase;
font-weight: bold;
}
.Row-annotation {
margin-inline-start: 16px;
@ -217,13 +230,14 @@ a:active {
height: 18px;
}
.Settings-setting input[type=range] {
.Settings-setting input[type="range"] {
width: 50px;
height: 18px;
}
.Settings-setting label {
margin-inline-start: 8px;
margin-inline-end: 8px;
}
.top-right {
@ -240,3 +254,13 @@ a:active {
.top-right a + a {
margin-inline-start: 8px;
}
.App-container.color-blind .letter-correct,
.App-container.color-blind .App-about b.green-bg {
background-color: #f5793a;
}
.App-container.color-blind .letter-elsewhere,
.App-container.color-blind .App-about b.yellow-bg {
background-color: #85c0f9;
}

Wyświetl plik

@ -35,6 +35,12 @@ function App() {
const [dark, setDark] = useSetting<boolean>("dark", prefersDark);
const [difficulty, setDifficulty] = useSetting<number>("difficulty", 2);
const [titleFormat, setTitleFormat] = useState<string>("inherit");
const [colorBlind, setColorBlind] = useSetting<boolean>("colorblind", false);
const [keyboard, setKeyboard] = useSetting<string>(
"keyboard",
"qwertyuiop-asdfghjkl-BzxcvbnmE"
);
const [enterLeft, setEnterLeft] = useSetting<boolean>("enter-left", false);
useEffect(() => {
switch (difficulty) {
@ -77,7 +83,7 @@ function App() {
);
return (
<div className="App-container">
<div className={"App-container" + (colorBlind ? " color-blind" : "")}>
<h1>
<span
style={{
@ -132,6 +138,15 @@ function App() {
/>
<label htmlFor="dark-setting">Dark theme</label>
</div>
<div className="Settings-setting">
<input
id="colorblind-setting"
type="checkbox"
checked={colorBlind}
onChange={() => setColorBlind((x: boolean) => !x)}
/>
<label htmlFor="colorblind-setting">Color blind mode</label>
</div>
<div className="Settings-setting">
<input
id="difficulty-setting"
@ -147,6 +162,7 @@ function App() {
<strong>
{["Baby", "Easy", "Normal", "Hard", "Ultra Hard"][difficulty]}
</strong>
<strong>{["Normal", "Hard", "Ultra Hard"][difficulty]}</strong>
<div
style={{
fontSize: 14,
@ -167,12 +183,40 @@ function App() {
</div>
</div>
</div>
<div className="Settings-setting">
<label htmlFor="keyboard-setting">Keyboard layout:</label>
<select
name="keyboard-setting"
id="keyboard-setting"
value={keyboard}
onChange={(e) => setKeyboard(e.target.value)}
>
<option value="qwertyuiop-asdfghjkl-BzxcvbnmE">QWERTY</option>
<option value="azertyuiop-qsdfghjklm-BzxcvbnE">AZERTY</option>
<option value="qwertzuiop-asdfghjkl-ByxcvbnmE">QWERTZ</option>
<option value="BpyfgcrlE-aoeuidhtns-qjkxbmwvz">Dvorak</option>
<option value="qwfpgjluy-arstdhneio-BzxcvbkmE">Colemak</option>
</select>
<input
style={{ marginLeft: 20 }}
id="enter-left-setting"
type="checkbox"
checked={enterLeft}
onChange={() => setEnterLeft((x: boolean) => !x)}
/>
<label htmlFor="enter-left-setting">"Enter" on left side</label>
</div>
</div>
)}
<Game
maxGuesses={maxGuesses}
hidden={page !== "game"}
difficulty={difficulty}
colorBlind={colorBlind}
keyboardLayout={keyboard.replaceAll(
/[BE]/g,
(x) => (enterLeft ? "EB" : "BE")["BE".indexOf(x)]
)}
/>
</div>
);

Wyświetl plik

@ -25,6 +25,8 @@ interface GameProps {
maxGuesses: number;
hidden: boolean;
difficulty: Difficulty;
colorBlind: boolean;
keyboardLayout: string;
}
const easyTargets = targetList.slice(0, targetList.indexOf("revel") + 1); // Slightly more frequent word on the list
@ -284,7 +286,11 @@ function Game(props: GameProps) {
>
{hint || `\u00a0`}
</p>
<Keyboard letterInfo={letterInfo} onKey={onKey} />
<Keyboard
layout={props.keyboardLayout}
letterInfo={letterInfo}
onKey={onKey}
/>
{gameState !== GameState.Playing && (
<p>
<button
@ -299,13 +305,16 @@ function Game(props: GameProps) {
</button>{" "}
<button
onClick={() => {
const emoji = props.colorBlind
? ["⬛", "🟦", "🟧"]
: ["⬛", "🟨", "🟩"];
share(
getChallengeUrl(target),
"Result copied to clipboard!",
guesses
.map((guess) =>
clue(guess, target)
.map((c) => ["⬛", "🟨", "🟩"][c.clue ?? 0])
.map((c) => emoji[c.clue ?? 0])
.join("")
)
.join("\n")

Wyświetl plik

@ -1,16 +1,19 @@
import { Clue, clueClass } from "./clue";
interface KeyboardProps {
layout: string;
letterInfo: Map<string, Clue>;
onKey: (key: string) => void;
}
export function Keyboard(props: KeyboardProps) {
const keyboard = [
"q w e r t y u i o p".split(" "),
"a s d f g h j k l".split(" "),
"Backspace z x c v b n m Enter".split(" "),
];
const keyboard = props.layout
.split("-")
.map((row) =>
row
.split("")
.map((key) => key.replace("B", "Backspace").replace("E", "Enter"))
);
return (
<div className="Game-keyboard" aria-hidden="true">

Wyświetl plik

@ -16981,7 +16981,7 @@
"gauntlet",
"crag",
"rodeo",
"squaw",
"*****",
"proliferate",
"evangelistic",
"tannin",