Python reference implementation of a serial-based Battleship game protocol for embedded systems projects.
The script communicates with another device (e.g. STM32 board) over UART using a framed binary protocol with CRC protection.
- Random Battleship field generation
- UART communication using framed messages
- CRC-8/SMBUS validation
- Cross-platform serial support (Linux & Windows)
- Tournament mode for automated testing
- Validation of opponent ship placement
- Cheat detection and protocol consistency checks
- Raw serial debugging support
- Python 3.x
- pyserial
Install dependencies:
pip install pyserialpython schiff.py <serial_device> [options]| Platform | Example |
|---|---|
| Linux | /dev/ttyUSB0 |
| Windows | COM23 |
| Argument | Description |
|---|---|
ser_dev |
Serial device path |
| Option | Description |
|---|---|
-v, --verbose |
Enable verbose debug logging |
-s, --single |
Play exactly one game |
-n, --notimeout |
Disable serial timeout handling |
-t, --tournament |
Run 100 automated games |
--raw-debug |
Print raw UART bytes sent and received |
python schiff.py /dev/ttyUSB0 -vpython schiff.py COM23 --verbosepython schiff.py COM23 --tournamentThe game uses a standard 10x10 Battleship field.
| Ship Length | Count |
|---|---|
| 5 | 1 |
| 4 | 2 |
| 3 | 3 |
| 2 | 4 |
Rules:
- Ships may only be placed horizontally or vertically
- Ships may not touch each other
- Surrounding cells must contain water
Communication uses framed binary packets.
[HEADER][MSG_ID][LEN][PAYLOAD][CRC][EOF]
| Field | Size | Description |
|---|---|---|
| HEADER | 1 byte | # |
| MSG_ID | 3 bytes | ASCII message identifier |
| LEN | 1 byte | Payload length |
| PAYLOAD | variable | Message payload |
| CRC | 1 byte | CRC-8/SMBUS |
| EOF | 1 byte | $ |
CRC configuration:
- Polynomial:
0x07 - Init:
0x00 - No reflection
- No final XOR
Compatible with STM32 hardware CRC configured for CRC-8.
| Message | ID | Description |
|---|---|---|
| START | STR |
Begin game |
| CHECKSUM | CSH |
Ship count checksum |
| SHIP FIELD | SFR |
Full ship field row |
| BOOM | BOO |
Fire at coordinates |
| BOOM RESULT | BMR |
Hit or miss result |
Starts a game session.
Payload:
- Optional ASCII player name
Example:
STR ""
Contains 10 ASCII digits.
Each digit represents the number of occupied cells in one row.
Example:
2332421607
Used after game completion.
Payload format:
[row_index][10 ASCII digits]
Example:
\x03 0000200000
Meaning:
- Row 3
- Ship part at column 4
Fire at coordinates.
Payload:
[row][column]
Example:
\x03\x04
Meaning:
- Fire at row 3, column 4
Returns hit or miss status.
| Value | Meaning |
|---|---|
H |
Hit |
M |
Miss |
Handles:
- UART communication
- Frame encoding/decoding
- CRC validation
- Timeouts
Responsible for:
- Random ship placement
- Shot handling
- Ship validation
- Exporting field records
Implements the Battleship protocol flow:
- Start handshake
- Exchange checksums
- Gameplay loop
- Endgame validation
Base class for targeting strategies.
Current implementation:
StupidFireSolutionUses random coordinates.
The script validates:
- Ship counts
- Ship sizes
- Straight ship placement
- Non-overlapping ships
- Water surrounding ships
- Correct hit/miss responses
- Valid checksum data
Protocol violations raise runtime errors.
Tournament mode automatically plays 100 games.
Output characters:
| Character | Meaning |
|---|---|
w |
We won |
l |
We lost |
a |
Aborted |
Final statistics are printed at the end.
Verbose logging:
python schiff.py COM23 -vRaw serial debugging:
python schiff.py COM23 --raw-debugShows transmitted and received UART bytes in hexadecimal format.
Educational / project use.