triple-triad-ff8 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- triple_triad_ff8-0.1.0/.gitignore +228 -0
- triple_triad_ff8-0.1.0/LICENSE +39 -0
- triple_triad_ff8-0.1.0/NOTICE +23 -0
- triple_triad_ff8-0.1.0/PKG-INFO +185 -0
- triple_triad_ff8-0.1.0/README.md +162 -0
- triple_triad_ff8-0.1.0/pyproject.toml +45 -0
- triple_triad_ff8-0.1.0/tests/__init__.py +1 -0
- triple_triad_ff8-0.1.0/tests/conftest.py +89 -0
- triple_triad_ff8-0.1.0/tests/test_ai.py +128 -0
- triple_triad_ff8-0.1.0/tests/test_board.py +148 -0
- triple_triad_ff8-0.1.0/tests/test_cards.py +100 -0
- triple_triad_ff8-0.1.0/tests/test_deck.py +200 -0
- triple_triad_ff8-0.1.0/tests/test_game.py +205 -0
- triple_triad_ff8-0.1.0/tests/test_rules.py +221 -0
- triple_triad_ff8-0.1.0/triple_triad/__init__.py +0 -0
- triple_triad_ff8-0.1.0/triple_triad/__main__.py +4 -0
- triple_triad_ff8-0.1.0/triple_triad/ai.py +47 -0
- triple_triad_ff8-0.1.0/triple_triad/board.py +195 -0
- triple_triad_ff8-0.1.0/triple_triad/cards.py +72 -0
- triple_triad_ff8-0.1.0/triple_triad/data/__init__.py +0 -0
- triple_triad_ff8-0.1.0/triple_triad/data/cards.py +143 -0
- triple_triad_ff8-0.1.0/triple_triad/deck.py +487 -0
- triple_triad_ff8-0.1.0/triple_triad/game.py +231 -0
- triple_triad_ff8-0.1.0/triple_triad/rules.py +117 -0
- triple_triad_ff8-0.1.0/triple_triad/synth/__init__.py +0 -0
- triple_triad_ff8-0.1.0/triple_triad/synth/constants.py +53 -0
- triple_triad_ff8-0.1.0/triple_triad/synth/melodies/__init__.py +0 -0
- triple_triad_ff8-0.1.0/triple_triad/synth/melodies/background_music.py +175 -0
- triple_triad_ff8-0.1.0/triple_triad/synth/player.py +113 -0
- triple_triad_ff8-0.1.0/triple_triad/synth/wave_generators.py +152 -0
- triple_triad_ff8-0.1.0/triple_triad/ui.py +43 -0
- triple_triad_ff8-0.1.0/uv.lock +178 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Byte-compiled / optimized / DLL files
|
|
13
|
+
__pycache__/
|
|
14
|
+
*.py[codz]
|
|
15
|
+
*$py.class
|
|
16
|
+
|
|
17
|
+
# C extensions
|
|
18
|
+
*.so
|
|
19
|
+
|
|
20
|
+
# Distribution / packaging
|
|
21
|
+
.Python
|
|
22
|
+
build/
|
|
23
|
+
develop-eggs/
|
|
24
|
+
dist/
|
|
25
|
+
downloads/
|
|
26
|
+
eggs/
|
|
27
|
+
.eggs/
|
|
28
|
+
lib/
|
|
29
|
+
lib64/
|
|
30
|
+
parts/
|
|
31
|
+
sdist/
|
|
32
|
+
var/
|
|
33
|
+
wheels/
|
|
34
|
+
share/python-wheels/
|
|
35
|
+
*.egg-info/
|
|
36
|
+
.installed.cfg
|
|
37
|
+
*.egg
|
|
38
|
+
MANIFEST
|
|
39
|
+
|
|
40
|
+
# PyInstaller
|
|
41
|
+
# Usually these files are written by a python script from a template
|
|
42
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
43
|
+
*.manifest
|
|
44
|
+
*.spec
|
|
45
|
+
|
|
46
|
+
# Installer logs
|
|
47
|
+
pip-log.txt
|
|
48
|
+
pip-delete-this-directory.txt
|
|
49
|
+
|
|
50
|
+
# Unit test / coverage reports
|
|
51
|
+
htmlcov/
|
|
52
|
+
.tox/
|
|
53
|
+
.nox/
|
|
54
|
+
.coverage
|
|
55
|
+
.coverage.*
|
|
56
|
+
.cache
|
|
57
|
+
nosetests.xml
|
|
58
|
+
coverage.xml
|
|
59
|
+
*.cover
|
|
60
|
+
*.py.cover
|
|
61
|
+
.hypothesis/
|
|
62
|
+
.pytest_cache/
|
|
63
|
+
cover/
|
|
64
|
+
|
|
65
|
+
# Translations
|
|
66
|
+
*.mo
|
|
67
|
+
*.pot
|
|
68
|
+
|
|
69
|
+
# Django stuff:
|
|
70
|
+
*.log
|
|
71
|
+
local_settings.py
|
|
72
|
+
db.sqlite3
|
|
73
|
+
db.sqlite3-journal
|
|
74
|
+
|
|
75
|
+
# Flask stuff:
|
|
76
|
+
instance/
|
|
77
|
+
.webassets-cache
|
|
78
|
+
|
|
79
|
+
# Scrapy stuff:
|
|
80
|
+
.scrapy
|
|
81
|
+
|
|
82
|
+
# Sphinx documentation
|
|
83
|
+
docs/_build/
|
|
84
|
+
|
|
85
|
+
# PyBuilder
|
|
86
|
+
.pybuilder/
|
|
87
|
+
target/
|
|
88
|
+
|
|
89
|
+
# Jupyter Notebook
|
|
90
|
+
.ipynb_checkpoints
|
|
91
|
+
|
|
92
|
+
# IPython
|
|
93
|
+
profile_default/
|
|
94
|
+
ipython_config.py
|
|
95
|
+
|
|
96
|
+
# pyenv
|
|
97
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
98
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
99
|
+
# .python-version
|
|
100
|
+
|
|
101
|
+
# pipenv
|
|
102
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
103
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
104
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
105
|
+
# install all needed dependencies.
|
|
106
|
+
# Pipfile.lock
|
|
107
|
+
|
|
108
|
+
# UV
|
|
109
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
110
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
111
|
+
# commonly ignored for libraries.
|
|
112
|
+
# uv.lock
|
|
113
|
+
|
|
114
|
+
# poetry
|
|
115
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
116
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
117
|
+
# commonly ignored for libraries.
|
|
118
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
119
|
+
# poetry.lock
|
|
120
|
+
# poetry.toml
|
|
121
|
+
|
|
122
|
+
# pdm
|
|
123
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
124
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
125
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
126
|
+
# pdm.lock
|
|
127
|
+
# pdm.toml
|
|
128
|
+
.pdm-python
|
|
129
|
+
.pdm-build/
|
|
130
|
+
|
|
131
|
+
# pixi
|
|
132
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
133
|
+
# pixi.lock
|
|
134
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
135
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
136
|
+
.pixi
|
|
137
|
+
|
|
138
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
139
|
+
__pypackages__/
|
|
140
|
+
|
|
141
|
+
# Celery stuff
|
|
142
|
+
celerybeat-schedule
|
|
143
|
+
celerybeat.pid
|
|
144
|
+
|
|
145
|
+
# Redis
|
|
146
|
+
*.rdb
|
|
147
|
+
*.aof
|
|
148
|
+
*.pid
|
|
149
|
+
|
|
150
|
+
# RabbitMQ
|
|
151
|
+
mnesia/
|
|
152
|
+
rabbitmq/
|
|
153
|
+
rabbitmq-data/
|
|
154
|
+
|
|
155
|
+
# ActiveMQ
|
|
156
|
+
activemq-data/
|
|
157
|
+
|
|
158
|
+
# SageMath parsed files
|
|
159
|
+
*.sage.py
|
|
160
|
+
|
|
161
|
+
# Environments
|
|
162
|
+
.env
|
|
163
|
+
.envrc
|
|
164
|
+
.venv
|
|
165
|
+
env/
|
|
166
|
+
venv/
|
|
167
|
+
ENV/
|
|
168
|
+
env.bak/
|
|
169
|
+
venv.bak/
|
|
170
|
+
|
|
171
|
+
# Spyder project settings
|
|
172
|
+
.spyderproject
|
|
173
|
+
.spyproject
|
|
174
|
+
|
|
175
|
+
# Rope project settings
|
|
176
|
+
.ropeproject
|
|
177
|
+
|
|
178
|
+
# mkdocs documentation
|
|
179
|
+
/site
|
|
180
|
+
|
|
181
|
+
# mypy
|
|
182
|
+
.mypy_cache/
|
|
183
|
+
.dmypy.json
|
|
184
|
+
dmypy.json
|
|
185
|
+
|
|
186
|
+
# Pyre type checker
|
|
187
|
+
.pyre/
|
|
188
|
+
|
|
189
|
+
# pytype static type analyzer
|
|
190
|
+
.pytype/
|
|
191
|
+
|
|
192
|
+
# Cython debug symbols
|
|
193
|
+
cython_debug/
|
|
194
|
+
|
|
195
|
+
# PyCharm
|
|
196
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
197
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
198
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
199
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
200
|
+
# .idea/
|
|
201
|
+
|
|
202
|
+
# Abstra
|
|
203
|
+
# Abstra is an AI-powered process automation framework.
|
|
204
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
205
|
+
# Learn more at https://abstra.io/docs
|
|
206
|
+
.abstra/
|
|
207
|
+
.kilocode/
|
|
208
|
+
|
|
209
|
+
# Visual Studio Code
|
|
210
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
211
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
212
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
213
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
214
|
+
# .vscode/
|
|
215
|
+
|
|
216
|
+
# Ruff stuff:
|
|
217
|
+
.ruff_cache/
|
|
218
|
+
|
|
219
|
+
# PyPI configuration file
|
|
220
|
+
.pypirc
|
|
221
|
+
|
|
222
|
+
# Marimo
|
|
223
|
+
marimo/_static/
|
|
224
|
+
marimo/_lsp/
|
|
225
|
+
__marimo__/
|
|
226
|
+
|
|
227
|
+
# Streamlit
|
|
228
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Your Name
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
─────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
THIRD-PARTY INTELLECTUAL PROPERTY NOTICE
|
|
26
|
+
|
|
27
|
+
"Final Fantasy", "Final Fantasy VIII", "Triple Triad", and all associated
|
|
28
|
+
character names, card names, creature names, and game mechanics are
|
|
29
|
+
trademarks and/or copyrighted material of Square Enix Holdings Co., Ltd.
|
|
30
|
+
All rights reserved.
|
|
31
|
+
|
|
32
|
+
This project is an unofficial, non-commercial fan work. It is not
|
|
33
|
+
affiliated with, endorsed by, or sponsored by Square Enix. All
|
|
34
|
+
Square Enix intellectual property is used here under fair use for
|
|
35
|
+
the purpose of creating a fan-made tribute.
|
|
36
|
+
|
|
37
|
+
The MIT License above applies solely to the original source code
|
|
38
|
+
written by the author(s) of this project. It does not grant any
|
|
39
|
+
rights to Square Enix's intellectual property.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
THIRD-PARTY INTELLECTUAL PROPERTY
|
|
2
|
+
==================================
|
|
3
|
+
|
|
4
|
+
This project references content from Final Fantasy VIII, originally
|
|
5
|
+
developed and published by Square Enix (formerly Squaresoft).
|
|
6
|
+
|
|
7
|
+
The following elements are the intellectual property of
|
|
8
|
+
Square Enix Holdings Co., Ltd.:
|
|
9
|
+
|
|
10
|
+
- The "Triple Triad" card game concept and rules
|
|
11
|
+
- Card names (e.g., Ifrit, Shiva, Quezacotl, Bahamut, etc.)
|
|
12
|
+
- Character names (e.g., Squall, Rinoa, Seifer, Quistis, etc.)
|
|
13
|
+
- Creature/monster names (e.g., Geezard, Malboro, Tonberry, etc.)
|
|
14
|
+
- Element system (Fire, Ice, Thunder, Earth, Poison, Wind, Water, Holy)
|
|
15
|
+
- The "Final Fantasy" and "Final Fantasy VIII" franchise names
|
|
16
|
+
|
|
17
|
+
This is an unofficial fan project created for educational and
|
|
18
|
+
entertainment purposes. It is distributed free of charge and
|
|
19
|
+
is not intended for commercial use.
|
|
20
|
+
|
|
21
|
+
No copyright infringement is intended. If you are a representative
|
|
22
|
+
of Square Enix and wish to request removal, please open an issue
|
|
23
|
+
on the project repository.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: triple-triad-ff8
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python implementation of the classic Triple Triad card game from Final Fantasy VIII
|
|
5
|
+
Author-email: Your Name <you@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: NOTICE
|
|
9
|
+
Keywords: card-game,cli,final-fantasy,game,triple-triad
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Games/Entertainment
|
|
16
|
+
Requires-Python: >=3.13
|
|
17
|
+
Requires-Dist: numpy>=2.4.4
|
|
18
|
+
Requires-Dist: pygame>=2.6.1
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
21
|
+
Requires-Dist: ruff>=0.15.8; extra == 'dev'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Triple-triad
|
|
25
|
+
|
|
26
|
+
A terminal-based Python implementation of the classic **Triple Triad** card game from *Final Fantasy VIII*, complete with chiptune background music, smart AI opponents, and support for official rules like Same, Plus, and Open.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## ✨ Features
|
|
31
|
+
|
|
32
|
+
- **Authentic gameplay** — 110 cards from FFVIII
|
|
33
|
+
- **3 difficulty levels** — Easy, Medium, and Hard CPU opponents with distinct AI strategies
|
|
34
|
+
- **Optional rules** — Open, Same, Plus, and Random capture mechanics
|
|
35
|
+
- **Chiptune music** — Retro-style background music generated with NumPy and played through Pygame
|
|
36
|
+
- **Interactive deck builder** — Browse, filter, and sort all cards before picking your hand
|
|
37
|
+
- **Deck presets** — Themed decks (Fire Power, Ice Wall, Thunder Rush, and more)
|
|
38
|
+
- **Terminal rendering** — ANSI-colored board with card ownership indicators
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🎮 How to Play
|
|
43
|
+
|
|
44
|
+
Triple Triad is a 2-player card game played on a 3×3 grid. Each player has 5 cards. Players take turns placing one card on the board. When a card is placed adjacent to an opponent's card, the touching sides are compared — if the attacker's value is higher, the defender's card is captured. The player with the most cards on the board at the end wins.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
┌──────────────────┬──────────────────┬──────────────────┐
|
|
48
|
+
│ │ │ │
|
|
49
|
+
│ [ 1 ] │ [ 2 ] │ [ 3 ] │
|
|
50
|
+
│ │ │ │
|
|
51
|
+
├──────────────────┼──────────────────┼──────────────────┤
|
|
52
|
+
│ ■Ifrit │ │ │
|
|
53
|
+
│ ▲ 9 │ [ 5 ] │ [ 6 ] │
|
|
54
|
+
│ ◀ 5 Ice 8 ▶ │ │ │
|
|
55
|
+
│ ▼ 6 │ │ │
|
|
56
|
+
├──────────────────┼──────────────────┼──────────────────┤
|
|
57
|
+
│ □Shiva │ │ │
|
|
58
|
+
│ ▲ 6 │ [ 8 ] │ [ 9 ] │
|
|
59
|
+
│ ◀ 6 Ice 9 ▶ │ │ │
|
|
60
|
+
│ ▼ 7 │ │ │
|
|
61
|
+
└──────────────────┴──────────────────┴──────────────────┘
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- **■** = Your card
|
|
65
|
+
- **□** = CPU's card
|
|
66
|
+
- Numbers inside empty cells = board position (1–9)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 🚀 Getting Started
|
|
71
|
+
|
|
72
|
+
### Prerequisites
|
|
73
|
+
|
|
74
|
+
- **Python 3.13+**
|
|
75
|
+
- **NumPy** (for audio synthesis)
|
|
76
|
+
- **Pygame** (for audio playback — optional, game runs silently without it)
|
|
77
|
+
|
|
78
|
+
### Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Clone the repository
|
|
82
|
+
git clone https://github.com/YOUR_USERNAME/triple-triad.git
|
|
83
|
+
cd triple-triad
|
|
84
|
+
|
|
85
|
+
# Install dependencies
|
|
86
|
+
uv sync --locked
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Run the Game
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python -m triple_triad.game
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 📦 Project Structure
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
triple_triad/
|
|
101
|
+
├── data/
|
|
102
|
+
│ └── cards.py # All 110 card definitions with stats & elements
|
|
103
|
+
├── synth/
|
|
104
|
+
│ ├── melodies/
|
|
105
|
+
│ │ └── background_music.py # Melody, chords, bass & percussion data
|
|
106
|
+
│ ├── constants.py # Note frequencies and sample rate
|
|
107
|
+
│ ├── player.py # Threaded chiptune player (pygame)
|
|
108
|
+
│ └── wave_generators.py # Square, triangle & noise wave synthesis
|
|
109
|
+
├── ai.py # CPU decision-making (random / greedy)
|
|
110
|
+
├── board.py # 3×3 grid state + ANSI terminal renderer
|
|
111
|
+
├── cards.py # Card class with immutable stats via CardStats
|
|
112
|
+
├── deck.py # Deck builders, presets & interactive picker
|
|
113
|
+
├── game.py # Main game loop and orchestration
|
|
114
|
+
├── rules.py # Capture logic (basic, Same, Plus)
|
|
115
|
+
└── ui.py # Display helpers and rule selection menu
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
## 🎵 Audio
|
|
120
|
+
|
|
121
|
+
The game includes a built-in chiptune soundtrack synthesized entirely in software:
|
|
122
|
+
|
|
123
|
+
- **5 channels**: melody, harmony, pad, bass, and percussion
|
|
124
|
+
- **Generated with NumPy** — no audio files required
|
|
125
|
+
- **Played through Pygame** — if Pygame is unavailable, the game runs silently
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🧩 Rules
|
|
130
|
+
|
|
131
|
+
| Rule | Description |
|
|
132
|
+
|------|-------------|
|
|
133
|
+
| **Open** | CPU's hand is visible to the player |
|
|
134
|
+
| **Same** | If 2+ adjacent cards share equal values, all are captured |
|
|
135
|
+
| **Plus** | If 2+ adjacent cards share equal value *sums*, all are captured |
|
|
136
|
+
| **Random** | Cards are dealt randomly from the full pool |
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 🛠 Development
|
|
141
|
+
|
|
142
|
+
### Install Dev Dependencies
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
uv sync --locked
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Run Tests
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
pytest
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Lint
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
ruff check .
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 🤝 Contributing
|
|
163
|
+
|
|
164
|
+
Contributions are welcome! Here's how to get started:
|
|
165
|
+
|
|
166
|
+
1. **Fork** the repository
|
|
167
|
+
2. **Create a feature branch** — `git checkout -b feature/my-feature`
|
|
168
|
+
3. **Make your changes** — follow the existing code style
|
|
169
|
+
4. **Run tests** — `pytest`
|
|
170
|
+
5. **Submit a pull request**
|
|
171
|
+
|
|
172
|
+
Please open an issue first for major changes to discuss the approach.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 📄 License
|
|
177
|
+
|
|
178
|
+
This project is for educational and personal use. Triple Triad is a minigame from *Final Fantasy VIII*, © Square Enix. All card names and game mechanics are the property of their respective owners.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 🙏 Acknowledgments
|
|
183
|
+
|
|
184
|
+
- **Square Enix** — for creating Triple Triad in *Final Fantasy VIII*
|
|
185
|
+
- The original card stats and element system are faithfully reproduced from the game
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Triple-triad
|
|
2
|
+
|
|
3
|
+
A terminal-based Python implementation of the classic **Triple Triad** card game from *Final Fantasy VIII*, complete with chiptune background music, smart AI opponents, and support for official rules like Same, Plus, and Open.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
- **Authentic gameplay** — 110 cards from FFVIII
|
|
10
|
+
- **3 difficulty levels** — Easy, Medium, and Hard CPU opponents with distinct AI strategies
|
|
11
|
+
- **Optional rules** — Open, Same, Plus, and Random capture mechanics
|
|
12
|
+
- **Chiptune music** — Retro-style background music generated with NumPy and played through Pygame
|
|
13
|
+
- **Interactive deck builder** — Browse, filter, and sort all cards before picking your hand
|
|
14
|
+
- **Deck presets** — Themed decks (Fire Power, Ice Wall, Thunder Rush, and more)
|
|
15
|
+
- **Terminal rendering** — ANSI-colored board with card ownership indicators
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🎮 How to Play
|
|
20
|
+
|
|
21
|
+
Triple Triad is a 2-player card game played on a 3×3 grid. Each player has 5 cards. Players take turns placing one card on the board. When a card is placed adjacent to an opponent's card, the touching sides are compared — if the attacker's value is higher, the defender's card is captured. The player with the most cards on the board at the end wins.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
┌──────────────────┬──────────────────┬──────────────────┐
|
|
25
|
+
│ │ │ │
|
|
26
|
+
│ [ 1 ] │ [ 2 ] │ [ 3 ] │
|
|
27
|
+
│ │ │ │
|
|
28
|
+
├──────────────────┼──────────────────┼──────────────────┤
|
|
29
|
+
│ ■Ifrit │ │ │
|
|
30
|
+
│ ▲ 9 │ [ 5 ] │ [ 6 ] │
|
|
31
|
+
│ ◀ 5 Ice 8 ▶ │ │ │
|
|
32
|
+
│ ▼ 6 │ │ │
|
|
33
|
+
├──────────────────┼──────────────────┼──────────────────┤
|
|
34
|
+
│ □Shiva │ │ │
|
|
35
|
+
│ ▲ 6 │ [ 8 ] │ [ 9 ] │
|
|
36
|
+
│ ◀ 6 Ice 9 ▶ │ │ │
|
|
37
|
+
│ ▼ 7 │ │ │
|
|
38
|
+
└──────────────────┴──────────────────┴──────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- **■** = Your card
|
|
42
|
+
- **□** = CPU's card
|
|
43
|
+
- Numbers inside empty cells = board position (1–9)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🚀 Getting Started
|
|
48
|
+
|
|
49
|
+
### Prerequisites
|
|
50
|
+
|
|
51
|
+
- **Python 3.13+**
|
|
52
|
+
- **NumPy** (for audio synthesis)
|
|
53
|
+
- **Pygame** (for audio playback — optional, game runs silently without it)
|
|
54
|
+
|
|
55
|
+
### Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Clone the repository
|
|
59
|
+
git clone https://github.com/YOUR_USERNAME/triple-triad.git
|
|
60
|
+
cd triple-triad
|
|
61
|
+
|
|
62
|
+
# Install dependencies
|
|
63
|
+
uv sync --locked
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Run the Game
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python -m triple_triad.game
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 📦 Project Structure
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
triple_triad/
|
|
78
|
+
├── data/
|
|
79
|
+
│ └── cards.py # All 110 card definitions with stats & elements
|
|
80
|
+
├── synth/
|
|
81
|
+
│ ├── melodies/
|
|
82
|
+
│ │ └── background_music.py # Melody, chords, bass & percussion data
|
|
83
|
+
│ ├── constants.py # Note frequencies and sample rate
|
|
84
|
+
│ ├── player.py # Threaded chiptune player (pygame)
|
|
85
|
+
│ └── wave_generators.py # Square, triangle & noise wave synthesis
|
|
86
|
+
├── ai.py # CPU decision-making (random / greedy)
|
|
87
|
+
├── board.py # 3×3 grid state + ANSI terminal renderer
|
|
88
|
+
├── cards.py # Card class with immutable stats via CardStats
|
|
89
|
+
├── deck.py # Deck builders, presets & interactive picker
|
|
90
|
+
├── game.py # Main game loop and orchestration
|
|
91
|
+
├── rules.py # Capture logic (basic, Same, Plus)
|
|
92
|
+
└── ui.py # Display helpers and rule selection menu
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
## 🎵 Audio
|
|
97
|
+
|
|
98
|
+
The game includes a built-in chiptune soundtrack synthesized entirely in software:
|
|
99
|
+
|
|
100
|
+
- **5 channels**: melody, harmony, pad, bass, and percussion
|
|
101
|
+
- **Generated with NumPy** — no audio files required
|
|
102
|
+
- **Played through Pygame** — if Pygame is unavailable, the game runs silently
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 🧩 Rules
|
|
107
|
+
|
|
108
|
+
| Rule | Description |
|
|
109
|
+
|------|-------------|
|
|
110
|
+
| **Open** | CPU's hand is visible to the player |
|
|
111
|
+
| **Same** | If 2+ adjacent cards share equal values, all are captured |
|
|
112
|
+
| **Plus** | If 2+ adjacent cards share equal value *sums*, all are captured |
|
|
113
|
+
| **Random** | Cards are dealt randomly from the full pool |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 🛠 Development
|
|
118
|
+
|
|
119
|
+
### Install Dev Dependencies
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
uv sync --locked
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Run Tests
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pytest
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Lint
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
ruff check .
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🤝 Contributing
|
|
140
|
+
|
|
141
|
+
Contributions are welcome! Here's how to get started:
|
|
142
|
+
|
|
143
|
+
1. **Fork** the repository
|
|
144
|
+
2. **Create a feature branch** — `git checkout -b feature/my-feature`
|
|
145
|
+
3. **Make your changes** — follow the existing code style
|
|
146
|
+
4. **Run tests** — `pytest`
|
|
147
|
+
5. **Submit a pull request**
|
|
148
|
+
|
|
149
|
+
Please open an issue first for major changes to discuss the approach.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 📄 License
|
|
154
|
+
|
|
155
|
+
This project is for educational and personal use. Triple Triad is a minigame from *Final Fantasy VIII*, © Square Enix. All card names and game mechanics are the property of their respective owners.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 🙏 Acknowledgments
|
|
160
|
+
|
|
161
|
+
- **Square Enix** — for creating Triple Triad in *Final Fantasy VIII*
|
|
162
|
+
- The original card stats and element system are faithfully reproduced from the game
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# NOTE: This project contains fan-created content referencing
|
|
2
|
+
# Square Enix intellectual property. It is distributed for
|
|
3
|
+
# non-commercial, educational, and entertainment purposes only.
|
|
4
|
+
[project]
|
|
5
|
+
name = "triple-triad-ff8"
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
description = "A Python implementation of the classic Triple Triad card game from Final Fantasy VIII"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Your Name", email = "you@example.com"},
|
|
13
|
+
]
|
|
14
|
+
keywords = ["game", "card-game", "triple-triad", "final-fantasy", "cli"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: End Users/Desktop",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: Games/Entertainment",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"numpy>=2.4.4",
|
|
25
|
+
"pygame>=2.6.1",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
triple-triad = "triple_triad.game:main"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"pytest>=9.0.2",
|
|
34
|
+
"ruff>=0.15.8",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[build-system]
|
|
38
|
+
requires = ["hatchling"]
|
|
39
|
+
build-backend = "hatchling.build"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["triple_triad"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# tests/__init__.py
|