> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inco.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Hangman

> Word-guessing game with the secret word encrypted on-chain

[Hangman](https://github.com/Inco-fhevm/hangman) is the classic word game with
the secret word kept encrypted on-chain. The player guesses letters, the contract
checks each guess against the hidden word, and only the player can decrypt their
own progress. No one, including the contract deployer, can read the word from
chain state.

Where [Mines](/games/mines) leans on the shuffle primitive, Hangman is a good
look at the core encrypted operations. Every guess is resolved with `e.eq`,
`e.or`, `e.and`, and `e.select` on encrypted values. The contract never branches
on a plaintext letter.

## How it works

A `HangmanFactory` holds a list of encrypted words. A master account seeds them
with `addWord` or `seedWords`, paying one `inco.getFee()` per word. Each word is a
4-character string packed into one `euint256` and stored encrypted.

To start a game, the factory picks a word and deploys a per-player
`HangmanGame`, granting that game access to the chosen word. The word index is
chosen pseudo-randomly from block data, but that only picks which entry to use.
The word itself stays encrypted, so the selection never leaks it.

The game holds all state encrypted, readable only by the player:

| State               | Type       | Meaning                              |
| ------------------- | ---------- | ------------------------------------ |
| `encryptedChars[4]` | `euint256` | the four letters of the word         |
| `revealed[4]`       | `ebool`    | which positions the player has found |
| `lives`             | `euint256` | starts at 8                          |
| `hasWon`            | `ebool`    | all four positions revealed          |

## Guessing a letter

`guessLetter` runs entirely on encrypted data:

```solidity theme={null}
// compare the guessed letter to every position, encrypted
ebool f = e.eq(encryptedChars[i], e.asEuint256(charCode));

// mark a position found if it matches (never overwrite a hit)
revealed[i] = e.or(revealed[i], f);

// won when all four positions are revealed
hasWon = e.and(e.and(revealed[0], revealed[1]), e.and(revealed[2], revealed[3]));

// lose a life only if the guess did not complete the word
lives = e.select(hasWon, lives, e.sub(lives, e.asEuint256(1)));
```

Every result handle is granted to the player with `e.allow`. The frontend
decrypts them off-chain to paint the board and show remaining lives. The contract
stores only handles, so the word and the running state never appear in the clear.

## Running it

The repo is a Next.js frontend plus a Hardhat contracts folder. It targets Base
Sepolia testnet.

```bash theme={null}
git clone https://github.com/Inco-fhevm/hangman.git

# contracts
cd hangman/contracts && bun install
bun hardhat compile
bun hardhat test --network baseSepolia

# frontend
cd .. && npm install && npm run dev   # http://localhost:3000
```

Set `PRIVATE_KEY`, `SEED_PHRASE`, and `BASE_SEPOLIA_RPC_URL` in `contracts/.env`
before deploying or testing.

## Honest note

This is a reference build, not a template. Words are fixed at 4 characters and a
game starts with 8 lives. The word list is seeded by a trusted master account.
Treat it as a worked example of doing game logic on encrypted values, not as
production code.
