Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/conventional-label.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# auto add labels to PRs
on:
pull_request_target:
types: [ opened, edited ]
name: conventional-release-labels
jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: bcoe/conventional-release-labels@v1
35 changes: 0 additions & 35 deletions .github/workflows/license_tests.yml

This file was deleted.

58 changes: 58 additions & 0 deletions .github/workflows/publish_stable.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Stable Release
on:
push:
branches: [master]
workflow_dispatch:

jobs:
publish_stable:
uses: TigreGotico/gh-automations/.github/workflows/publish-stable.yml@master
secrets: inherit
with:
branch: 'master'
version_file: 'pyfrotz/version.py'
setup_py: 'setup.py'
publish_release: true

publish_pypi:
needs: publish_stable
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install Build Tools
run: |
python -m pip install build wheel
- name: version
run: echo "::set-output name=version::$(python setup.py --version)"
id: version
- name: Build Distribution Packages
run: |
python setup.py sdist bdist_wheel
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{secrets.PYPI_TOKEN}}


sync_dev:
needs: publish_stable
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
ref: master
- name: Push master -> dev
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: dev
108 changes: 108 additions & 0 deletions .github/workflows/release_workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Release Alpha and Propose Stable

on:
pull_request:
types: [closed]
branches: [dev]

jobs:
publish_alpha:
if: github.event.pull_request.merged == true
uses: TigreGotico/gh-automations/.github/workflows/publish-alpha.yml@master
secrets: inherit
with:
branch: 'dev'
version_file: 'pyfrotz/version.py'
setup_py: 'setup.py'
update_changelog: true
publish_prerelease: true
changelog_max_issues: 100

notify:
if: github.event.pull_request.merged == true
needs: publish_alpha
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Send message to Matrix bots channel
id: matrix-chat-message
uses: fadenb/matrix-chat-message@v0.0.6
with:
homeserver: 'matrix.org'
token: ${{ secrets.MATRIX_TOKEN }}
channel: '!WjxEKjjINpyBRPFgxl:krbel.duckdns.org'
message: |
new ${{ github.event.repository.name }} PR merged! https://github.com/${{ github.repository }}/pull/${{ github.event.number }}

publish_pypi:
needs: publish_alpha
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: dev
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install Build Tools
run: |
python -m pip install build wheel
- name: version
run: echo "::set-output name=version::$(python setup.py --version)"
id: version
- name: Build Distribution Packages
run: |
python setup.py sdist bdist_wheel
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{secrets.PYPI_TOKEN}}


propose_release:
needs: publish_alpha
if: success() # Ensure this job only runs if the previous job succeeds
runs-on: ubuntu-latest
steps:
- name: Checkout dev branch
uses: actions/checkout@v3
with:
ref: dev

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.10'

- name: Get version from setup.py
id: get_version
run: |
VERSION=$(python setup.py --version)
echo "VERSION=$VERSION" >> $GITHUB_ENV

- name: Create and push new branch
run: |
git checkout -b release-${{ env.VERSION }}
git push origin release-${{ env.VERSION }}

- name: Open Pull Request from dev to master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Variables
BRANCH_NAME="release-${{ env.VERSION }}"
BASE_BRANCH="master"
HEAD_BRANCH="release-${{ env.VERSION }}"
PR_TITLE="Release ${{ env.VERSION }}"
PR_BODY="Human review requested!"

# Create a PR using GitHub API
curl -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token $GITHUB_TOKEN" \
-d "{\"title\":\"$PR_TITLE\",\"body\":\"$PR_BODY\",\"head\":\"$HEAD_BRANCH\",\"base\":\"$BASE_BRANCH\"}" \
https://api.github.com/repos/${{ github.repository }}/pulls

19 changes: 5 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
# Changelog

All notable changes to this project will be documented in this file.
## [0.2.1a1](https://github.com/TigreGotico/pyFrotz/tree/0.2.1a1) (2025-12-20)

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
[Full Changelog](https://github.com/TigreGotico/pyFrotz/compare/374fa123b2ac695fcc84234cc95d52535c7b31d6...0.2.1a1)

## [Unreleased]
**Merged pull requests:**

## [0.1.5] - 2019-12-12
- chore: Configure Renovate [\#1](https://github.com/TigreGotico/pyFrotz/pull/1) ([renovate[bot]](https://github.com/apps/renovate))

### Changed

- Transfered ownership to [OpenJarbas](https://github.com/OpenJarbas)
- Made a changelog

### Fixed

- changed default interperter path to path used by setup.py

[unreleased]: https://github.com/OpenJarbas/pyFrotz/tree/dev
[0.1.5]: https://github.com/OpenJarbas/pyFrotz/tree/0.1.5
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
133 changes: 133 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/TigreGotico/pyFrotz)

# PyFrotz

**PyFrotz** is a minimal Python wrapper around [Frotz](https://gitlab.com/DavidGriffith/frotz), a popular interpreter for Infocom's text adventure games. It complies with the Z-Machine Standard version 1.1, making it compatible with classic interactive fiction.

<img src='./pyfrotz/gui/all/pyfrotz.png' card_color='#00ff00' width='150' height='150' style='vertical-align:bottom'/>

Get some classic games to try [@The Obsessively Complete Infocom Catalog](https://eblong.com/infocom/).

Source code for a lot of infocom games can be found [@historicalsource](https://github.com/historicalsource)

---

## Installation

First, install the PyFrotz Python package via pip:

```bash
pip install pyfrotz
```

Additionally, ensure you have [dfrotz](https://gitlab.com/DavidGriffith/frotz.git) installed on your system. It is often packaged as `frotz-dumb` in Linux distributions.

---

## Usage

PyFrotz can be used programmatically or interactively in the command line interface (CLI).

### Programmatic Usage

```python
from pyfrotz import Frotz

# Load your game file
data = '/path/to/your/game/data.z5'
game = Frotz(data)

# Interact with the game in your code
game_intro = game.get_intro()
room, description = game.do_command("look")
game.save() # Optionally pass filename, default='save.qzl'
game.restore() # Optionally pass filename, default='save.qzl'
```

### CLI Gameplay

You can also play games directly in the CLI:

```python
from pyfrotz import Frotz

data = '/path/to/your/game/data.z5'

game = Frotz(data)
game.play_loop()
```

---

## OVOS Skills

PyFrotz can be used as a voice interpreter for all Infocom and other Z-Machine games.

An OpenVoiceOS template class is provided to wrap games into a skill.

### Template OVOS Class: `FrotzSkill`

The `FrotzSkill` class is a template for creating conversational game skills based on PyFrotz. It simplifies the integration of Z-Machine games with OpenVoiceOS by handling game state, input/output, and optional auto-save features.

#### Features

- **Game Initialization**: Automatically loads the game data and prepares the save file location.
- **Intro Parser**: Parses and announces the game's introductory text when starting a new game.
- **Command Handling**: Pipes user inputs to the game, processes the output, and optionally translates input/output for multilingual support.
- **Save/Load Management**: Handles game saving and restoring with customizable dialogs.
- **GUI Integration**: Updates the OVOS GUI with game-specific visuals during gameplay.
- **Abandon Game Handling**: Manages mid-interaction abandonment with optional auto-save.

#### Example Usage

Below is an example of how to use the `FrotzSkill` template to wrap a game like *Zork* into an OVOS skill.

```python
from pyfrotz.ovos import FrotzSkill


class ZorkSkill(FrotzSkill):
def __init__(self, *args, **kwargs):
super().__init__(
game_id="zork",
game_data="/path/to/zork.z5",
game_lang="en",
skill_icon="/path/to/zork/icon.png",
game_image="/path/to/zork/bg.png",
*args, **kwargs
)
```

To package this into an OVOS skill:

1. Set the game-specific parameters (`game_id`, `game_data`, `game_lang`, etc.).
2. Customize dialogs and GUI assets (e.g., images and icons) as needed.
3. Override methods like `on_play_game`, `on_game_command`, or `on_abandon_game` for additional functionality.
4. Include a `{game_id}.voc` file in the `locale` directory, listing various ways the game can be referred to by voice. The file name must match the `game_id` with a `.voc` suffix (e.g., `zork.voc`).

#### Key Methods

- **`on_play_game`**: Initializes the game and displays the introductory text.
- **`on_save_game`**: Saves the current game state to a file.
- **`on_load_game`**: Restores the game state from a save file.
- **`on_stop_game`**: Handles cleanup when the game ends.
- **`on_game_command(utterance, lang)`**: Processes user commands, with optional language translation.

### Existing Game Skills

Several prebuilt OVOS skills based on PyFrotz are available:

- [Planetfall Game](https://github.com/JarbasSkills/ovos-skill-planet-fall-game)
- [Stationfall Game](https://github.com/JarbasSkills/ovos-skill-station-fall-game)
- [Starcross Game](https://github.com/JarbasSkills/ovos-skill-starcross-game)
- [The Hitchhiker's Guide to the Galaxy](https://github.com/JarbasSkills/ovos-skill-hhgg-game)
- [White House Adventure](https://github.com/OVOSHatchery/ovos-skill-white-house-adventure)
- [Zork II](https://github.com/JarbasSkills/ovos-skill-zork2-game)
- [Zork III](https://github.com/JarbasSkills/ovos-skill-zork3-game)
- [Zork 0](https://github.com/JarbasSkills/ovos-skill-zork0-game)
- [Colossal Cave Adventure](https://github.com/OVOSHatchery/ovos-skill-cave-adventure-game)

---

Enjoy bringing these timeless text-based adventures to life with PyFrotz!

Loading