Compare commits

...

7 Commits

Author SHA1 Message Date
eb6abf9c8c chore: remove local artifacts
Some checks failed
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / docker-build (push) Has been cancelled
CI / security (push) Has been cancelled
CI / build-result (push) Has been cancelled
2026-08-21 17:15:29 +00:00
Jarian
0dba12d694 ci: re-trigger merge 2026-07-06 00:29:05 +00:00
Jarian
fc4ec11521 ci: re-trigger 20260706001829 2026-07-06 00:18:29 +00:00
Jarian
020603d173 Merge branch 'fix/all' 2026-07-05 22:23:41 +00:00
jarianc
fc9d88c995 Merge pull request 'CI: remove --no-cache for docker layer caching' (#15) from ci-fix-nocache into main
Reviewed-on: https://git.home.ms/jarianc/exorcist-game/pulls/15
2026-07-04 22:22:25 -05:00
Jarian
db639b0cec CI: remove --no-cache for docker layer caching 2026-07-05 03:11:47 +00:00
Jarian
fe1bbf8530 CI: add generalized workflow 2026-07-05 02:46:27 +00:00
8 changed files with 175 additions and 131 deletions

143
.gitea/workflows/ci.yml Normal file
View File

@ -0,0 +1,143 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
env:
GITEA_URL: https://git.home.ms
jobs:
lint:
runs-on: ubuntu-latest
container:
image: gitea-job-image
steps:
- name: Clone repo
run: |
rm -rf $GITHUB_WORKSPACE/*
git clone --depth 1 $GITEA_URL/$GITHUB_REPOSITORY $GITHUB_WORKSPACE
git -C $GITHUB_WORKSPACE checkout $GITHUB_SHA 2>/dev/null || true
- name: Run ruff (Python lint)
if: always()
run: |
if [[ -f pyproject.toml ]]; then
pip3 install ruff
ruff check .
else
echo "No Python project detected, skipping ruff"
fi
- name: Run npm lint (JS/TS)
if: always()
run: |
if [[ -f package.json ]]; then
npm ci
npm run lint --if-present || true
else
echo "No Node.js project detected, skipping npm lint"
fi
test:
runs-on: ubuntu-latest
container:
image: gitea-job-image
steps:
- name: Clone repo
run: |
rm -rf $GITHUB_WORKSPACE/*
git clone --depth 1 $GITEA_URL/$GITHUB_REPOSITORY $GITHUB_WORKSPACE
git -C $GITHUB_WORKSPACE checkout $GITHUB_SHA 2>/dev/null || true
- name: Run pytest (Python)
if: always()
run: |
if [[ -f pyproject.toml ]]; then
python3 -m pip install --upgrade pip
pip3 install -e ".[dev]" 2>/dev/null || pip3 install -e . 2>/dev/null || true
pip3 install pytest
pytest tests/ -v --tb=short 2>/dev/null || true
else
echo "No Python project detected, skipping pytest"
fi
- name: Run npm test (JS/TS)
if: always()
run: |
if [[ -f package.json ]]; then
npm ci
npm run test --if-present || true
else
echo "No Node.js project detected, skipping npm test"
fi
- name: Run Go tests
if: always()
run: |
if [[ -f go.mod ]]; then
go test ./...
else
echo "No Go project detected, skipping go test"
fi
docker-build:
runs-on: ubuntu-latest
steps:
- name: Clone repo
run: |
rm -rf $GITHUB_WORKSPACE/*
git clone --depth 1 $GITEA_URL/$GITHUB_REPOSITORY $GITHUB_WORKSPACE
git -C $GITHUB_WORKSPACE checkout $GITHUB_SHA 2>/dev/null || true
- name: Build Docker image
if: always()
run: |
if [[ -f Dockerfile ]]; then
docker build -t $GITHUB_REPOSITORY:test .
else
echo "No Dockerfile found, skipping docker build"
fi
security:
runs-on: ubuntu-latest
container:
image: gitea-job-image
steps:
- name: Clone repo
run: |
rm -rf $GITHUB_WORKSPACE/*
git clone --depth 1 $GITEA_URL/$GITHUB_REPOSITORY $GITHUB_WORKSPACE
git -C $GITHUB_WORKSPACE checkout $GITHUB_SHA 2>/dev/null || true
- name: Run bandit (Python SAST)
if: always()
run: |
if [[ -f pyproject.toml ]]; then
pip3 install bandit
bandit -r . --severity-level high --confidence-level high --exclude tests/,test_*
else
echo "No Python project detected, skipping bandit"
fi
- name: Run npm audit (JS/TS)
if: always()
run: |
if [[ -f package.json ]]; then
npm ci
npm audit --audit-level=high 2>/dev/null || echo "npm audit: vulnerabilities found (non-blocking)"
else
echo "No Node.js project detected, skipping npm audit"
fi
build-result:
needs: [lint, test, docker-build, security]
runs-on: ubuntu-latest
container:
image: gitea-job-image
if: always()
steps:
- name: Summary
run: echo "All CI checks completed"

155
README.md
View File

@ -1,148 +1,41 @@
# Arcane Purge
# Exorcist Game (Arcane Purge)
A text-based exorcist game where Bible verses are your weapons against demonic forces. Type verses from Scripture to cast spells, pass memory tests to defeat demons, and unlock progressively more powerful verses as you advance.
A text-based exorcist game where Bible verses are the spell mechanics. Fight through a gauntlet of escalating demons by matching verse categories to each demon's weaknesses.
## What It Does
> Personal prototype project — functional, but not polished.
Arcane Purge is a terminal-based game that combines Scripture memorization with demon-slaying gameplay:
## Gameplay
- **Verse Casting** - Select a verse, then type it exactly to deal damage to demons. Verses matching a demon's weakness deal double damage.
- **Memory Tests** - After a successful cast, recall the same verse without looking. Passing delivers a powerful finishing strike.
- **Progression** - Start with 4 easy verses. Defeating demons unlocks harder verses and new categories. After 5 demons, Memory Mode activates.
- **Scoring** - Points awarded for correct casts, speed bonuses, memory test success, and demon defeats. Deducted for failures.
- **Hint System** - Press `H` at any input to see the first letter of each word.
## Setup and Dependencies
### Requirements
- Python 3.11+
- Astral UV (for dependency management)
- Docker (for containerized deployment)
### Install with UV
```bash
uv sync
```
This installs all dependencies listed in `pyproject.toml` (currently `pytest` for testing).
### Install with pip
```bash
pip install pytest
```
## How to Run
### Docker (Recommended)
```bash
cd docker
docker compose up --build
```
This builds the game container and starts it in interactive mode. The game runs inside the container with a TTY attached for input.
To run tests inside the container:
```bash
cd docker
docker compose run game python -m pytest tests -v
```
### Direct Python
```bash
python main.py
```
### Running Tests
```bash
python -m pytest tests/ -v
```
The test suite includes 34 tests covering data loading, text normalization, verse filtering, similarity matching, hint generation, and game initialization.
- Terminal-based combat loop with timer pressure
- Six escalating demon encounters, each with health, damage, and elemental weaknesses
- Verse-based spell system: recite verses from the right category (Binding, Healing, Exorcism, Protection, Judgment) to deal damage
- Mismatched categories fizzle — read the demon, pick the verse
## Project Structure
```
exorcist-game/
├── .dockerignore # Docker build exclusions
├── .env.example # Environment variable template
├── .hadolint.yaml # Dockerfile linting config
├── pyproject.toml # Project metadata and dependencies
├── uv.lock # UV dependency lock file
├── verses.json # Bible verse data (12 verses, 5 categories)
├── data.py # Verse loading, filtering, text normalization
├── main.py # Game engine: encounters, casting, scoring
├── docker/
│ ├── docker-compose.yml # Service orchestration
│ └── Dockerfile # Multi-stage container build
├── tests/
│ ├── test_data.py # Data module tests (21 tests)
│ └── test_main.py # Game logic tests (13 tests)
└── README.md # This file
```
| Path | Description |
|------|-------------|
| `main.py` | Game engine, demon definitions, and combat loop |
| `data.py` | Verse loading, normalization, and spell resolution |
| `verses.json` | Verse dataset |
| `docker/` | Dockerfile and compose for containerized runs |
| `tests/` | Test suite for verse data and game logic |
### Key Modules
## Running
| File | Purpose |
|---|---|
| `main.py` | Game loop, demon encounters, verse casting, memory tests, scoring, progression |
| `data.py` | Verse data loading from JSON, category/difficulty filtering, text normalization |
| `verses.json` | 12 verses across 5 categories (Binding, Healing, Exorcism, Protection, Judgment) |
| `tests/` | Validation suite ensuring data integrity and game logic correctness |
## Configuration and Environment Variables
### Environment Variables
Copy `.env.example` to `.env` and configure:
### Local
```bash
PYTHON_VERSION=3.12-slim # Python version for Docker base image
GAME_PORT=8080 # (Reserved for future web interface)
uv sync
python main.py
```
The game runs without environment variables configured. All game data is embedded in `verses.json`.
### Verse Data Format
Each verse in `verses.json` follows this structure:
```json
{
"id": "binding_001",
"text": "Full verse text here.",
"category": "Binding",
"difficulty": 1,
"reference": "Luke 10:19"
}
```
### Adding Verses
Append new verse objects to the `verses` array in `verses.json`. Difficulty must be 1-5.
### Adding Demons
Edit the `DEMONS` list in `main.py`:
```python
{"name": "Demon Name", "health": 100, "weaknesses": ["Binding", "Exorcism"], "damage": 20}
```
### Code Quality
The project uses Ruff for linting and Hadolint for Dockerfile validation:
### Docker
```bash
ruff format .
ruff check --fix .
hadolint docker/Dockerfile
docker compose -f docker/docker-compose.yml up
```
All checks must pass before building the container.
## Status
Working prototype. Built as an experiment in terminal game design; not actively maintained.

Binary file not shown.

Binary file not shown.

Binary file not shown.

8
prompt_v0.2.md Normal file
View File

@ -0,0 +1,8 @@
we need to implement the following key features
- Add 100 more Bible verses (ensure these are the Biblically accurate scriptures and are the ESV or KJV version)
- Give the user the option to pick which version from the start screen
- Add some dialog lines in between the battles.
- Add a tutorial level where a mentor teaches you how to face a demon.
- Keep these features in the cli version of the game, but go ahead and make a web version of the game so that people can play this from a browser
- On the web version, let the user be able to speak out the verses into their mic. We can use whisper.cpp on the backend to transcribe the audio. You can download what models you need, but try to use the bare minimum for now during testing as my internet speed is not great (40-50 Mbps)
- The user will need to still be very accurate with the wordings from the verses.