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 Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

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

Uploaded CPython 3.13Windows x86-64

movablegames-0.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (229.9 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

movablegames-0.2.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl (245.5 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ i686

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

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 10.13+ x86-64

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

Uploaded CPython 3.12Windows x86-64

movablegames-0.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (229.5 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

movablegames-0.2.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (245.8 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ i686

movablegames-0.2.6-cp312-cp312-macosx_11_0_arm64.whl (159.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

movablegames-0.2.6-cp312-cp312-macosx_10_13_x86_64.whl (170.0 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

File details

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

File metadata

File hashes

Hashes for movablegames-0.2.6-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 338ca6592a2d384bb45bbbd7222f8262e21811fa2c981200da42f99ccddb372e
MD5 d2f9f9bbac6516490a1c7f295fa46c16
BLAKE2b-256 e3c8333105fc3428b5a75a69af6bc6eaf3ff7c8ad024bbf88c06aa6452cb3892

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-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.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 01ce65256adaf5150a363a6cf161ca313133fb8f2c4624b6984e08b2ab082d4c
MD5 05dc688f89dd7e9c4b71f24d081b2e53
BLAKE2b-256 b8395dcff09987205bc49864727f15d2d30cec63c0d0850a1895ce2ef92fc4aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_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.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c3af97eeaabb519e0077c264660c673c0caff0e28982f1be7f6329cbf087230c
MD5 373c336b9f2d1e8ab696243a32fc6fcb
BLAKE2b-256 7197b4ab015fc97396628fb6ff3e4c93c238b952e29857b20b410476a143c8d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.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.6-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 67c6399ce3d006284033819d28bf0e2944aafb9a4501e9e4dc86f34758f5fd82
MD5 0b9484134060a66f3ea5d21cf90f1a64
BLAKE2b-256 65f255aea5e7d3e42d763e1c5e30b46e14ce2e70189be6f2366a5c1102fc6db9

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-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.6-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 92d8c1f88ecc2d772e6f3cb4eece3a3b6a247d83b5f91e1b27c39feb046dafd3
MD5 7a4c5999a4ad8134de1bb7209210b7e7
BLAKE2b-256 e17f46f0d9cefc6776a691b0d0b9416e52acd693a968bdabb6019485d1563532

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-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.6-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 e5f1c9bf999c49491da9ae86dde5c20979c4667695bb57a702a0f8dbbb755f63
MD5 32b43bb93a38d083d1d154e6612819e2
BLAKE2b-256 64844f0e60937c5f5aecd38d84686fc734feff99db86e84a4a50fffc38fc8958

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-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.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2c9283cc6385c1f57c14c70c1aa004dc1d397a65b2ccd78c09d098bddb2e1c26
MD5 de285e035b2207ac49f0b645f6d8e4b7
BLAKE2b-256 d6bb9d385f1422b1c851909684158e6dee5e1874c4b6b2936234273a34ebc623

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_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.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 1637b95f285f014e0b825f2855cb0827a12d0deba80ea853372704f57f7d02b1
MD5 1ce27fc2400c2d9298232ef64336324c
BLAKE2b-256 5249cafdbabd501b52ee7e6d8c14c39bd359d0ac72033f4145e174cf2df02fae

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.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.6-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0e41455c1c6c53b31f31cf548299af2627dbb66255dd1c815e381ae0ab6036b8
MD5 58e39513774c2f4664f8a929ecf7dd8c
BLAKE2b-256 b8bb7cb8c2bd002f53481e394f41f43e7255c6b18edf380e9b9ba36d83dc26ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-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.6-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.6-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 d0024e13a27d7b8056d7791664fc90a334aa2f9b1e01297ef64a42974fd419f9
MD5 d8e0d6efa56a15199cb918e21ef5c4a7
BLAKE2b-256 9adef689f710f8ba327a2fb740ea24bd70607632b9be58dc0422d0de9fa23640

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.6-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