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.8.tar.gz (175.6 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.8-cp313-cp313-win_amd64.whl (185.0 kB view details)

Uploaded CPython 3.13Windows x86-64

movablegames-0.2.8-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.8-cp313-cp313-macosx_11_0_arm64.whl (159.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 10.13+ x86-64

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

Uploaded CPython 3.12Windows x86-64

movablegames-0.2.8-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.8-cp312-cp312-macosx_11_0_arm64.whl (159.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

movablegames-0.2.8-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.8.tar.gz.

File metadata

  • Download URL: movablegames-0.2.8.tar.gz
  • Upload date:
  • Size: 175.6 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.8.tar.gz
Algorithm Hash digest
SHA256 d0a30269cfa305f473a61f5221f4eb8547bfd12ab07f3af65e2f335a8599a857
MD5 70a6d84e385db80b3bcbec371e33371e
BLAKE2b-256 ad5943a35c1bef2e5ea76fc601127c8862eb93bb3f25609f69aa012e3ded3829

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.8.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.8-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.8-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 4787c37b48e35b1c8ebc52f70d21443afb7650ee1f1f5f2368fb7f687285e891
MD5 1023f1dee9916e7dc368fffec0c6340d
BLAKE2b-256 76b0c5f24c322aabccec90bc509e13f73c43acc292ae59dd9ec3ef912af30e39

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.8-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.8-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.8-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5a48425ec2dde8f41c5a51c0595cce142153329d8a7c3c52b4ffad7829203913
MD5 1035986841249f9035e66fdb39626383
BLAKE2b-256 8de40ec7cf10d1c0b554f797bfc77771d4319d7af21d2aa2a7468796ac7e0416

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.8-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.8-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.8-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ef96dd8b34d8f031decf98ac87598eb8744eb8725123bd65918bd05cb0bef702
MD5 dd8b4a71c476dffebdf0e3c5f3897d5c
BLAKE2b-256 b43243b459712349954c720890903e1ca28d0755cd528926914172552be06c15

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.8-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 55df741b92f3f55b7b10e9b27c078b3187a22028dcddad0669cd4244aa967333
MD5 9cd01981eae7b5c1786511cc9eb07348
BLAKE2b-256 0e7129ff0c9c1bf8b08d6f20aafc9959305848db15b3cc7eb7a97beefae1cba5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 4aa21e96b43da76415a5ee6aa6d3cb67c640009492011ae379e3ce8c83d4c557
MD5 0f3ecf634e037b8c8916c0c55542b008
BLAKE2b-256 71e27a05f402f9ff248d203760427aed65717634d179f84b9275765401050080

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.8-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.8-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.8-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3587775d4323e6cdca16140be215989de6033698ffd5b0c6e0c76ea15f952786
MD5 1b1ffe5844b3898d542757842aff6d4a
BLAKE2b-256 f4ad48582d87c18cb3d71ba76834d3f70b31c059a9491daabd53774d4cbf048e

See more details on using hashes here.

Provenance

The following attestation bundles were made for movablegames-0.2.8-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.8-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for movablegames-0.2.8-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dff3bcba9a6224ac8b07483f494c733c35903c31d517c57c6d254f795cd373a7
MD5 0acd1b2eaf44743b6c2bff85bbf15f3b
BLAKE2b-256 204554c7a30d2c76b9f391295ba2046be96be719762eb4bda817374c406cd058

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.8-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 1b5dd4e316897f41c3fe3eeda20ffbc8e4152f786a62bb6d16b623549500332c
MD5 8498167cd7214cf3372dd9edfd17512a
BLAKE2b-256 5ebbaea0bf91b5a0fa91c8dd38f0dc14033f18e865d25a4a8d081b1bcad4f2ff

See more details on using hashes here.

Provenance

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