Skip to main content

AI-powered adaptive game engine for educational platforms

Project description

MovableGames Python API

The movablegames package is a thin Python facade over the pybind11-compiled mag_engine C++ wheel. It provides the building blocks for generating educational game environments, producing narrative frame sequences, and dispatching problems across all supported subjects.


Installation

From wheel (production):

pip install movablegames

Editable / source build (requires CMake 3.25+, vcpkg, a C++17 compiler):

uv pip install -e .
# or
pip install -e .

The build compiles the C++ engine with BUILD_PYTHON_BINDINGS=ON and places the resulting .pyd / .so alongside the pure-Python modules. See engine/README.md for C++ build details.


Package layout

python/movablegames/
├── __init__.py        re-exports everything from mag_engine (C++ bindings)
├── environment.py     EnvironmentFactory, HistoryEnvironment
├── level.py           MathLevelGenerator, ProblemGenerator
├── sequencer.py       NarrativeManager
└── topics.py          Topic enum, TopicManager

Core types, from the C++ bindings (mag_engine)

These are re-exported by __init__.py via from .mag_engine import *.

ChargePolarity

from movablegames import ChargePolarity

ChargePolarity.POSITIVE   # numbers > 0
ChargePolarity.NEGATIVE   # numbers < 0
ChargePolarity.NEUTRAL    # variables / dormant entities

Charge

Represents a number as a physical entity.

from movablegames import Charge, ChargePolarity

c = Charge(magnitude=3.0, polarity=ChargePolarity.POSITIVE, visual_id="c_01")
c.magnitude    # float
c.polarity     # ChargePolarity
c.visual_id    # str, unique identifier for the frontend renderer
c.to_json()    # str, JSON representation

Environment

A container for charges and mathematical operators (agents). Supports nested sub-environments (parentheses).

from movablegames import Environment

env = Environment("zone_main")

# Add a charge directly
env.add_charge(magnitude=5.0, polarity=ChargePolarity.POSITIVE, visual_id="c_01")

# Add operator agents
env.add_plus_magician("m_plus_01")
env.add_minus_magician("m_minus_01")
env.add_multiply_magician("m_mul_01")
env.add_divide_magician("m_div_01")
env.add_power_sorcerer("m_pow_01")
env.add_root_magician("m_root_01")
env.add_abs_magician("m_abs_01")
env.add_factorial_magician("m_fac_01")
env.add_modulo_magician("m_mod_01")
env.add_log_magician("m_log_01")
env.add_chronomancer("m_chrono_01")       # parenthesis handler

# Add validation gates
env.add_equals_gate("gate_01", target=42.0)
env.add_inequality_gate("gate_02", target=10.0, comparison_type=">")

# Nest a sub-environment (parenthesis bubble)
sub = Environment("zone_sub")
env.add_sub_environment(sub)

# Inspect state
env.id                    # str
env.charges               # list[Charge]
env.agents                # list[MagicianAgent]
env.sub_environments      # list[Environment]
env.is_time_frozen        # bool

env.to_json()             # str, full JSON snapshot of the environment

NarrativeSequencer

Drives the game loop one step at a time, applying operator priority rules (BIDMAS/BODMAS) and producing a JSON event for each step.

from movablegames import NarrativeSequencer

seq = NarrativeSequencer(env)

while not seq.is_finished:
    frame_json = seq.next_frame()   # str, JSON with status and event data
    print(frame_json)

seq.current_frame    # int, index of the last processed frame
seq.is_finished      # bool

Frame event types (values of the "status" key in frame JSON):

Constant Meaning
CAST_SPELL An operator agent acted on charges
COLLAPSE_ZONE A parenthesis bubble resolved
LEVEL_COMPLETE All operators finished; gate validates
ERROR An unrecoverable error occurred
FINISHED Simulation is done (no more frames)
RUNNING Step completed; simulation continues

Python wrappers

EnvironmentFactory, movablegames.environment

Factory that builds typed Environment objects from level data dictionaries.

from movablegames.environment import EnvironmentFactory

env = EnvironmentFactory.create_math_environment(level_data)
env = EnvironmentFactory.create_science_environment(level_data)
env = EnvironmentFactory.create_history_environment(level_data)   # returns HistoryEnvironment
env = EnvironmentFactory.create_english_environment(level_data)
env = EnvironmentFactory.create_technology_environment(level_data)

level_data is the dict returned by MathLevelGenerator.generate_math_problem or any ProblemGenerator.* method. See the Level data schema section below.

Operator role → add_* method mapping (EnvironmentFactory.MAG_MAGICIAN_METHODS):

Role string Method
"plus" add_plus_magician
"minus" add_minus_magician
"multiply" add_multiply_magician
"divide" add_divide_magician
"power" add_power_sorcerer
"root" add_root_magician
"abs" add_abs_magician
"factorial" add_factorial_magician
"modulo" add_modulo_magician
"log" add_log_magician

MathLevelGenerator, movablegames.level

Generates a random, self-consistent math problem and its level data.

from movablegames.level import MathLevelGenerator

expr_str, level_data = MathLevelGenerator.generate_math_problem(
    operators=["+", "-", "*", "/"],   # subset of MAG_OPERATORS keys; None = all
    difficulty="easy",                # "easy" | "medium" | "hard"
)

Supported operator symbols (MathLevelGenerator.MAG_OPERATORS):

Symbol Role
"+" plus
"-" minus
"*" multiply
"/" divide
"**" or "^" power
"root" root
"abs" abs
"!" factorial
"%" modulo
"log" log

Difficulty parameters:

Difficulty Operators Max value Max complexity
"easy" 1–2 10 2 (+ − × ÷ abs)
"medium" 2–4 20 3 (adds power, root, modulo)
"hard" 4–6 50 5 (all operators)

ProblemGenerator, movablegames.level

Placeholder generators for non-math subjects. Return a (problem_string, level_data) tuple suitable for the corresponding EnvironmentFactory.create_* method.

from movablegames.level import ProblemGenerator

problem, data = ProblemGenerator.generate_science_problem(difficulty="easy")
problem, data = ProblemGenerator.generate_history_problem(difficulty="medium")
problem, data = ProblemGenerator.generate_english_problem(difficulty="hard")
problem, data = ProblemGenerator.generate_technology_problem(difficulty="easy")

NarrativeManager, movablegames.sequencer

Runs the full narrative loop and collects all frames into a list.

from movablegames.sequencer import NarrativeManager

frames = NarrativeManager.get_frames(environment=env, env_type="math")
# Returns list[dict], first entry is the initial state, subsequent entries are
# NarrativeSequencer frames; each dict has a "current_frame" index added.

Raises ValueError for unsupported env_type values.


Topic / TopicManager, movablegames.topics

from movablegames.topics import Topic, TopicManager

Topic.MATH         # "MATH"
Topic.SCIENCE      # "SCIENCE"
Topic.HISTORY      # "HISTORY"
Topic.ENGLISH      # "ENGLISH"
Topic.TECHNOLOGY   # "TECHNOLOGY"

TopicManager.get_all_topics()
# → ["math", "science", "history", "english", "technology"]

Level data schema

MathLevelGenerator.generate_math_problem returns a dict with this shape:

{
  "level_id": "gen_easy_3f2a1b4c",
  "environment": {
    "zones": [
      {
        // The primary zone holding all top-level charges and operators
        "id": "zone_main",
        "type": "main_environment",
        "contents": [
          {
            "type": "charge",
            "value": 5.0,
            "polarity": "positive",
            "id": "c_a1b2",
          },
          { "type": "magician", "role": "plus", "id": "m_plus_c3d4" },
        ],
      },
      {
        // Optional: a parenthesis bubble (sub-environment)
        "id": "zone_e5f6",
        "type": "parenthesis_bubble",
        "contents": [
          {
            "type": "charge",
            "value": 3.0,
            "polarity": "positive",
            "id": "c_g7h8",
          },
          {
            "type": "charge",
            "value": 2.0,
            "polarity": "negative",
            "id": "c_i9j0",
          },
          { "type": "magician", "role": "minus", "id": "m_minus_k1l2" },
        ],
      },
      {
        // The goal gate, the equation target
        "id": "gate_main",
        "type": "equals_gate", // or "inequality_gate"
        "target_value": 6.0,
        // For inequality_gate only:
        // "comparison": ">" | "<" | ">=" | "<="
      },
    ],
  },
}

End-to-end example

from movablegames.level import MathLevelGenerator
from movablegames.environment import EnvironmentFactory
from movablegames.sequencer import NarrativeManager

# 1. Generate a medium-difficulty problem using addition and multiplication
expr_str, level_data = MathLevelGenerator.generate_math_problem(
    operators=["+", "*"],
    difficulty="medium",
)
print(f"Problem: {expr_str}")

# 2. Build the environment from the level data
env = EnvironmentFactory.create_math_environment(level_data)

# 3. Collect all narrative frames
frames = NarrativeManager.get_frames(env, env_type="math")
print(f"Total frames: {len(frames)}")

# 4. Inspect the first and last frames
import json
print("Initial state:", json.dumps(frames[0], indent=2))
print("Final state:  ", json.dumps(frames[-1], indent=2))

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

movablegames-0.2.9.tar.gz (177.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

movablegames-0.2.9-cp313-cp313-win_amd64.whl (185.0 kB view details)

Uploaded CPython 3.13Windows x86-64

movablegames-0.2.9-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (223.7 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

movablegames-0.2.9-cp313-cp313-macosx_11_0_arm64.whl (159.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

movablegames-0.2.9-cp313-cp313-macosx_10_13_x86_64.whl (170.2 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

movablegames-0.2.9-cp312-cp312-win_amd64.whl (185.0 kB view details)

Uploaded CPython 3.12Windows x86-64

movablegames-0.2.9-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (223.8 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

movablegames-0.2.9-cp312-cp312-macosx_11_0_arm64.whl (159.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

movablegames-0.2.9-cp312-cp312-macosx_10_13_x86_64.whl (170.1 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

File details

Details for the file movablegames-0.2.9.tar.gz.

File metadata

  • Download URL: movablegames-0.2.9.tar.gz
  • Upload date:
  • Size: 177.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for movablegames-0.2.9.tar.gz
Algorithm Hash digest
SHA256 de0d03ab28816d8cacc8d402e3f57023e412c1f08fdb9665972623d48ff6c6eb
MD5 78d5053c9690e64cbc9bca47d6f98183
BLAKE2b-256 b516ea58b73418acef7d468d82b595c8ecd5f4c4c83af98a2d7daaed823f7e1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9.tar.gz:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 6257d24d7151eb72825e4acbe2858319642eb5b4ec2249702d27d52c3b69b2bf
MD5 ce519c74bdbe5adf78fb64dbc798e5c4
BLAKE2b-256 f68e83492e7032a293585567311e3696fce8cf7615efa5c50089abd60d49e65c

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp313-cp313-win_amd64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4b2e06fbab00deb79c73f1a45d1c463216113f918a6c353a53d036e820587b67
MD5 7808b2eecc2e50babe3227a1235aaccf
BLAKE2b-256 7b26cf8d663bc6f6f9fd9c34a46039161b54b64e3e4b331d597469c4dac3c510

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2c66b554e6f5282edadf17e2c55c56c259842937d7b2891df5ae8d30610aad7a
MD5 b6a0e26c3bf6b657dd807259b8aec705
BLAKE2b-256 51e94face315a692c7bd2fbdcf8fd25d3cc26ac1e7ae9d4fbdcb22f70541201e

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 87cefc113252b524682b4783cba02659ce58b1e97ece023518ab5cd33d038221
MD5 3d032957162c121b74623f4ee1ccc75a
BLAKE2b-256 66d767c1a97a502e66b435edaed429529b63e4b0f53443f3f6949c0677068b62

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp313-cp313-macosx_10_13_x86_64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b3aa88903a629b94b0f320acb1dd8dde8b9661d32116e6ed35fb1e1e4ad348b7
MD5 a9a0a7b0b46fae65d27d6a709848d05a
BLAKE2b-256 eee6a6b46f4ed815d22a2337217a25c7b0550fec9030b5d2b19170b246c50ee9

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp312-cp312-win_amd64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b8e7a30fee0ce5b3b6e83b3fcf7845152b37e8842771d0e2e0ee3d511a1dedcd
MD5 c5c499550b6d243eedf142884278d6a6
BLAKE2b-256 c656480b9aa7efd34bb041517fb7f0048d00fdb6c176cfa1e4ec03225b5fcc85

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f8b034ad621359aef5c64fa1594020fb1bc9a5b6deffa7fdf733bb8ff4a6a4e9
MD5 d8bd8ab91adcd25c6ddf88aef4f91dab
BLAKE2b-256 5b11db6b102daa1faaf2dd210e2b2f84a0f4ae518cd4156c798051b37001c7f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movablegames-0.2.9-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.9-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 e2a1d509136cad143cba82d05fc6a9bf9290b029678dd0ccc918b235ee27b601
MD5 b2575dce79f88d386df7f593bab8e3cd
BLAKE2b-256 6a2ec4790debd1e30c54f6284d743908ac0a1a69e948271d2293dd60286d3acb

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.9-cp312-cp312-macosx_10_13_x86_64.whl:

Publisher: publish_pypi.yml on MovableGames/MovableGames

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page