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

Uploaded CPython 3.13Windows x86-64

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

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 10.13+ x86-64

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

Uploaded CPython 3.12Windows x86-64

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

Uploaded CPython 3.12macOS 11.0+ ARM64

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

File metadata

  • Download URL: movablegames-0.2.7.tar.gz
  • Upload date:
  • Size: 181.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.7.tar.gz
Algorithm Hash digest
SHA256 eff05f86124ae9ce7eaf83ef38fc2d7de2abaf3faeb89b7fbe41b337a513abdb
MD5 5d14457a2f0a9299f5d32c1465890379
BLAKE2b-256 1a7ee6d58b2b49c4ddea1dbbe5feb7483e2ebed291164e4efaa5062f95577a7f

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 fa7bfe63abb8d11c917fd76178eafead197d96e86123fc6cd5dc6bd64a096d43
MD5 ea25e82bca386fd523a9f98f016fc968
BLAKE2b-256 6c232022f2d8f4854f7136944ffe2d8da45903ba2dc2bd96f32203d2743fb5c5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a9256d738186a03a6330f4ffd1f43b688d845b94641828c2a54d9b589d1d0d72
MD5 2db696c5e595b92c9ffb8f622c0a71b1
BLAKE2b-256 68d44a076707543703b1dd77976c7eb33a561cedff3e297deb89220f36b8d736

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b96d57ea7d4886096dca6da1d52d3d1969bc051775575b5c91f1dcda55d2a7fa
MD5 d186fd1c0f886bceaec1ffac5d3a3747
BLAKE2b-256 8b5fb6d30517775a7cedbad8a42ef6a5c59f209ec147481b61bbf6cdc3a42951

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 e5f54bc770a00898f2dd148b1a0a492a5c39d043a1c63c8ee11dc114afce112d
MD5 bab4257880eb63a9ef7b6fda0af0b778
BLAKE2b-256 8a36e919a9091df61967ece411d0a6eb592e662fc6100e4168679c96d454ef43

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 02baa90d666808b4fa5cb8c2883b1d7ea122c6818c836568c51bfbc1ae73b975
MD5 b327848bfc374fd335242d9f8d760cae
BLAKE2b-256 b6da3b396a8168bee6646403ec9e4edfd3f4fb88430ff88af2cd7b128f2caabc

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e4f30af5430c0ea5f31d9c3b14ee8c54bd7b5c6d3fb1ce021fb844487f8e5937
MD5 862a5cf231e8188a9f6025202c75e659
BLAKE2b-256 c7268efc6217c7b48ef4de716d2a173e18842e015139990797d3ae90aff41157

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9977ce6661135f0ff5938be460bdb7e99e60dae35e33119f775c658c1040d12e
MD5 8ede6595c7b9685f79894516a34ecb1d
BLAKE2b-256 761960d9979853e32c071846dc514769b929d403318b5dcb5a58697229bf3732

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for movablegames-0.2.7-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 4131e1cef50ce6ea214fcd01398f622f41e9c8b39a85b7145cdcf9d711e35100
MD5 74a5579a78bd1a6d8211d83b24abc0ff
BLAKE2b-256 046b5e8ea7e333bef7643aaa5aa2c34341961cb4e32ea7f5c76bb872aae529ee

See more details on using hashes here.

Provenance

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