Metadata-Version: 2.4
Name: 32word
Version: 0.1.3
Summary: The game engine for 3-2-Word: Solve Wordle in three guesses.
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# 32word

**The game engine for 3-2-Word: Solve Wordle in three guesses.**

[![PyPI version](https://badge.fury.io/py/32word.svg)](https://badge.fury.io/py/32word)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)

## What This Is

Most people play Wordle casually. Guess some vowels. Eliminate common letters. Hope for the best. Maybe they've heard that STAIR + LEMON + PUDGY is unbeatable.

We know better.

**3-2-Word** is a training app that elevates Wordle from a casual puzzle into something you can practice and masterâ€”like Scrabble or a spelling bee. This library (`32word`) is the engine underneath.

Smart players solved Wordle years ago. They proved optimal strategies mathematically. But most people didn't change how they played. This library changes that. It codifies the strategies that work and makes them accessible to everyone.

**It's fun to challenge yourself. It's fun to be smart.** This gives you the tools to win.

## Installation

```bash
pip install 32word
```

## Why This Exists

You can solve Wordle blindly, or you can learn the patterns that elite players discovered through exhaustive analysis. This library provides:

1. **Optimal two-guess strategies** that consistently solve Wordle in three attempts
2. **Pre-computed strategy tables** based on simulations across all 3,158 target words
3. **A clean API** for building bots, websites, and training tools

The solver logic lives here. Everything elseâ€”web apps, Discord bots, Telegram botsâ€”imports this library as a dependency.

## Quick Start

```python
from word32 import generate_clue, filter_targets, load_strategy, get_second_guess

# Load the default optimal strategy
strategy = load_strategy("v1.0")

# Get the best first guess
first_guess = strategy.first_guess()
print(f"First guess: {first_guess}")  # e.g., "STARE"

# Simulate Wordle feedback
target = "TRASH"
clue = generate_clue(first_guess, target)
print(f"Clue: {clue}")  # ('G', 'Y', 'B', 'B', 'G')

# Find remaining possibilities
from word32 import VALID_TARGETS
remaining = filter_targets(VALID_TARGETS, first_guess, clue)
print(f"{len(remaining)} words remain")

# Get optimal second guess
second_guess = get_second_guess(strategy, clue)
print(f"Second guess: {second_guess}")
```

Two guesses. Then solve. That's the strategy.

## Core API

### Clue Generation

```python
generate_clue(guess: str, target: str) -> tuple[str, str, str, str, str]
```

Returns a 5-tuple representing Wordle's feedback:
- `'G'`: Green (correct letter, correct position)
- `'Y'`: Yellow (correct letter, wrong position)  
- `'B'`: Black/Gray (letter not in target)

**Example:**
```python
generate_clue("STARE", "TRASH")
# ('G', 'Y', 'B', 'B', 'G')
# S is green (position 0 matches)
# T is yellow (in word, wrong position)
# A, R are gray (not in target at those positions)
# E is green (position 4 matches)
```

### Target Filtering

```python
filter_targets(targets: list[str], guess: str, clue: tuple) -> list[str]
```

Returns all words in `targets` that would produce exactly `clue` if you guessed `guess` against them.

**Example:**
```python
remaining = filter_targets(VALID_TARGETS, "STARE", ('G', 'Y', 'B', 'B', 'G'))
# Returns list of words compatible with that clue pattern
```

### Strategy Loading

```python
load_strategy(version: str = "v1.0") -> Strategy
```

Loads a pre-computed strategy table. The default `v1.0` uses expected-remaining minimization over all 3,158 Wordle targets.

**Strategy methods:**
```python
strategy = load_strategy("v1.0")

# Get recommended first guess
first = strategy.first_guess()

# Get recommended second guess based on clue
second = strategy.second_guess(clue)

# Get strategy metadata
meta = strategy.metadata()
```

### Convenience Functions

```python
get_second_guess(strategy: Strategy, first_clue: tuple) -> str
```
Shortcut for getting the optimal second guess.

```python
is_valid_word(word: str) -> bool
```
Check if a word is in Wordle's valid guess list (14,855 words).

```python
get_remaining_candidates(targets: list[str], guess: str, clue: tuple) -> int
```
Count how many targets remain after a guess.

## Strategy Design

Each strategy is a lookup table built from tournament simulations. The process:

1. **First guess selection**: Test every valid target word as a first guess against all 3,158 possible Wordle targets
2. **Clue simulation**: For each first guess, generate all possible clues (up to 243 patterns, though most never occur)
3. **Second guess optimization**: For each (first_guess, clue) pair, find the second guess that minimizes expected remaining candidates
4. **Tournament ranking**: Score strategies by expected remaining words after two guesses across all targets

The default `v1.0` strategy consistently leaves 1â€“3 candidates after two guesses, making the third guess nearly deterministic.

### Strategy Metadata

```python
strategy = load_strategy("v1.0")
meta = strategy.metadata()

print(meta)
# {
#   'version': 'v1.0',
#   'penalty_function': 'expected_remaining',
#   'depth': 2,
#   'symmetric': True,
#   'created': '2026-01-15',
#   'description': 'Optimal two-deep strategy minimizing expected remaining targets'
# }
```

## Complete Example

```python
from word32 import (
    generate_clue,
    filter_targets,
    load_strategy,
    get_second_guess,
    VALID_TARGETS
)

# Load strategy
strategy = load_strategy("v1.0")

# Simulate a game
target = "TRASH"  # The word Wordle picked
remaining = VALID_TARGETS.copy()

# First guess
guess1 = strategy.first_guess()
clue1 = generate_clue(guess1, target)
remaining = filter_targets(remaining, guess1, clue1)
print(f"After '{guess1}': {len(remaining)} words remain")

# Second guess
guess2 = get_second_guess(strategy, clue1)
clue2 = generate_clue(guess2, target)
remaining = filter_targets(remaining, guess2, clue2)
print(f"After '{guess2}': {len(remaining)} words remain")

# Third guess
if len(remaining) == 1:
    print(f"Solved in 3: {remaining[0]}")
elif len(remaining) <= 3:
    print(f"Choose from: {remaining}")
else:
    # Edge case handling
    print(f"Manual selection needed from {len(remaining)} candidates")
```

Most games end after two optimal guesses with 1â€“3 candidates remaining.

## Architecture

This library is designed as a **single source of truth** for Wordle solver logic. All downstream applications (website, bots, mobile apps) import this package.

```
32word (PyPI library)
  â†“
  â”œâ”€ 3-2-Word website (React + Flask/FastAPI)
  â”œâ”€ Discord bot
  â”œâ”€ Telegram bot
  â”œâ”€ Signal bot
  â””â”€ WhatsApp bot (future)
```

### Design Principles

- **Stateless**: All functions are deterministic and side-effect-free
- **Fast**: Word lists cached in memory, strategy tables pre-computed
- **Tested**: 95%+ coverage on core logic (clue generation, filtering)
- **Versioned**: Strategy tables versioned independently from library code
- **Simple API**: Six core functions cover all use cases

## Development

### Running Tests

```bash
pip install -e ".[dev]"
pytest tests/ -v --cov=word32
```

### Package Structure

```
word32/
â”œâ”€â”€ __init__.py           # Public API exports
â”œâ”€â”€ core.py               # Clue generation, filtering
â”œâ”€â”€ strategy.py           # Strategy loading and lookup
â”œâ”€â”€ validation.py         # Word list validation
â”œâ”€â”€ data/
â”‚   â”œâ”€â”€ strategies/
â”‚   â”‚   â””â”€â”€ v1.0.json     # Pre-computed optimal strategy
â”‚   â”œâ”€â”€ targets.txt       # 3,158 Wordle targets
â”‚   â””â”€â”€ valid_guesses.txt # 14,855 valid guesses
â””â”€â”€ tests/
    â”œâ”€â”€ test_clues.py
    â”œâ”€â”€ test_filtering.py
    â”œâ”€â”€ test_strategy.py
    â””â”€â”€ test_integration.py
```

### Creating New Strategies

Strategy tables are JSON files in `word32/data/strategies/`:

```json
{
  "metadata": {
    "version": "v1.1-minimax",
    "penalty_function": "minimax",
    "depth": 2,
    "created": "2026-01-20"
  },
  "first_guess": "SALET",
  "clues": {
    "GGGGG": {"second_guess": "N/A", "remaining": 0},
    "GGGYB": {"second_guess": "BLAND", "remaining": 2},
    ...
  }
}
```

To add a new strategy:
1. Run the tournament simulation to generate the table
2. Save as `v{X}.{Y}-{variant}.json`
3. Submit a PR with test coverage

## Roadmap

### Phase 1: Core Library âœ…
- [x] Clue generation
- [x] Target filtering
- [x] Strategy loading
- [x] Pre-computed v1.0 strategy
- [x] PyPI package

### Phase 2: Downstream Apps (In Progress)
- [ ] Website at 3-2-word.com
- [ ] Discord bot
- [ ] Telegram bot
- [ ] Signal bot
- [ ] WhatsApp bot

### Future Extensions
- [ ] Three-deep strategies
- [ ] Minimax variants
- [ ] Anchor word customization
- [ ] Quordle/Weaver support
- [ ] Strategy comparison analytics

## Why MIT Licensed?

This code should be free. The insights are already publishedâ€”researchers solved Wordle years ago. I'm just packaging it so anyone can use it.

Build a bot. Build a training app. Build a better solver. The game is solved. Now go teach people how to win.

## Contributing

Contributions welcome! Please:

1. **Open an issue** before starting major work
2. **Write tests** for new features
3. **Follow the existing style** (stateless functions, simple API)
4. **Update docs** if you change the API

### Areas for Contribution

- **New strategies**: Minimax, three-deep, custom anchor words
- **Performance**: Optimize filtering, caching
- **Variants**: Quordle, Absurdle, other Wordle clones
- **Tests**: Edge cases, integration tests
- **Docs**: Tutorials, strategy explanations

## Related Projects

- **3-2-Word website**: [3-2-word.com](https://3-2-word.com)
- **Discord bot**: Coming soon
- **Telegram bot**: Coming soon

## Acknowledgments

Built on the shoulders of researchers who solved Wordle mathematically. This library packages their insights for practical use.

Special thanks to the Wordle community for exploring optimal strategies and making the game more interesting.

## License

MIT License. See [LICENSE](LICENSE) for details.

---

**3-2-Word**: The training app for people who want to master Wordle.  
Built by Ben Mazzotta. Engine: `32word`.

**Get better at Wordle. Start here.**
