Upload failed. Maybe wrong permissions?

User Tools

Site Tools

LDraw Model Programming Language


A Draft Idea for Lego CAD Software Developers

Version 1.00

14th February, 2002

1. What Is LMPL?

LDraw Model Programming Language is the child concept of the LCD (LDraw Connection Database) concept. It is a modelling language, intended to give “life” to an LDraw scenario: to make virtual Lego models move.
  LMPL may be implemented to virtual Lego CAD softwares equipped with the LCD system. LMPL is strongly based on LCD.

1.1. What Can LMPL Solve?

Lego CAD softwares currently being used are CAD softwares capable for building with Lego elements and nothing more.
  A future Lego CAD software, equipped with the LCD system, will be an enhanced form of a CAD software, making building with Lego elements easier and nothing more.
  When a Lego CAD software receives the LMPL extension, it won’t be a CAD software any longer. It will become a full-fledged Lego building and playing area, both for children and for adult researchers, usable for playing with toys and for physical experiments – almost for all purposes Lego itself is suitable for.

1.2. Notes And Abbreviations

In this document, numbers like 3001 refer to numbers of Lego parts, as registered in Lego CAD software. When writing the document, we have used MLCAD 2.00 with the parts list from the archive complete.exe, downloaded from www.ldraw.org, archived at 30th September, 2000.
  On the other hand, numbers preceded with “set”, like set 918, refer to numbers of official Lego sets or idea books, according to the documentation available at www.brickshelf.com. Referring to a page of a set means the given picture file of the set; i.e. set 8020, page 2 means 8020-02.jpg in the appropriate folder on BrickShelf.
  Abbreviations used in this document:

LCD – LDraw Connection Database. A proposal developed by myself to make virtual Lego building easier. When the development of this document has begun, the work to make LCD a really usable proposal was in the earliest stage. This document refers to LCD as if being a fully completed task, not just a proposal, but an implemented extension in MLCAD, LeoCAD or other Lego CAD software.
  LCS – Local Coordinate System. A coordinate system specific to each connection. For details, refer to the LCD documentation.
  ML – stands for Movcons’ List. See sections 2.1. and 2.5.
  Movcon: stands for movable connection.
  Scenario: a full model or group of models built in an LDraw compatible software and stored in the same file, being visible in the same virtual space.

All trademarks mentioned in this document are property of their respective owners.

2. The Idea Of The Language

The idea is to create a language designed to move virtual Lego creations. It is strictly based on real Lego-like movement; it isn’t intended to turn a house into a car in a step or make a car to run through a wall unobstacled. LMPL doesn’t aim anything what is impossible with real Lego; but it can be used to realize movements what are difficult in real Lego, such as moving hundreds of models at the same time.

The idea is maintaining a database of movcons. A movcon (movable connection) is a connection between two virtual Lego parts built in an LDraw model in a movable way. For example, see the crane truck in set 6000, pages 6–7. This is a simple vehicle, but contains several movcons:
  a) 4 connections between the wheels and the road (assumed to be);
  b) 2 connections between the axles and their holders;
  c) the hinge holding the crane;
  d) a connection inside the winch (rotating part with stable part);
  e) a connection between the winch and the cable;
  f) an indefinite number of movcons inside the cable;
  g) a connection between the cable and the hook;
  h) a connection between the hook and the cargo (assumed to be).

The LCD system knows the following:
  1. what types of connection are movcons;
  2. what types of movement can a specific movcon do;
  3. how the movconning parts will change when a movcon is moving;
  4. what parts to move together with them.

The LMPL system knows the following:
  5. where are movcons built in our scenario;
  6. among these, what are important and what are not;
  7. what commands can a specific movcon obey to.

Assembling all of these, we can instruct movcons to change their state – they can be made either or both to slide or rotate. According to LCD specifications, this will make our full models to move or change state.

2.1. What Types Of Connection Are Movcons?

The answer is simple. Any standard LCD connection is a movcon if the connecting parts may make any movement according to each other, still being connected. For example, two Gears connecting make a movcon, but two 3001 Bricks don’t.
  When connecting two parts, the LCD system checks if it is a movcon, that is, if there is any possible movement registered for that type of connection. If yes, the LCD system adds the connection to the Movcons’ List. This is a list maintained together with the scenario, storing information about all currently existing movcons.

2.2. What Types Of Movement Can A Specific Movcon Do?

For each possible LCD connection, the LCD database stores information about allowed movements. These can be arranged into two groups: slides and rotations.
  A slide can take place along any linear direction; this direction is stored in angle figures compared to the LCS of the connection, including coordinate figures about the allowed end points of the sliding, if any.
  A rotation can take place around any center axis; this is stored in angle figures compared to the LCS of the connection, including angle figures about the allowed end points of the rotation, if any.
  Therefore, when examining a movcon, we will find all required information in the LCD database to know how to move it.
  When a movcon is moving, it may either slide or rotate, or do both in the same time. It may slide northwards or southwards; it may rotate clockwise or counterclockwise. It may do a small movement, a millimeter or an arc minute; it may move for a longer distance or a greater angle; or it may start a continuous movement until a command to stop is received. Or, of course, it may be standing moveless. Which case will happen, depends on the user’s intentions.

2.3. How The Movconning Parts Will Change When A Movcon Is Moving?

In most cases, they will change their location. When sliding, their coordinates are shifted but the direction of their polygons remain the same. When rotating, the direction of their polygons change, too.
  An Axle pushed through an Axlehole may slide as long as the Axlehole reaches an end of the Axle. This will change the coordinates of the Axle. Or, on the other hand, the Axle may stay where it is and the Brick containing the Axlehole may move instead. And, of course, both parts may move in the same time, with different speeds, in the same or different direction. The end point is expressed in coordinate figures, so we won’t check if there is virtual Lego substance inside the Axlehole but check coordinates instead.
  A Hinge may rotate around its central axle until the two parts overlap. Either or both of the two parts may rotate. The end point is expressed in angle figures, so we won’t check if the coordinates overlap, we check the angle of turning instead.
  Two Gears connecting make a bit trickier movcon. This movcon doesn’t rotate around itself, that is, around the point where the gearteeth have met – instead, both Gears are rotating around their own centers, in the opposite direction, and the speed depends on the difference of their sizes. We will need a specifically designed gear rotator algorithm for this.
  A Wheel running on a surface makes another tricky movcon. It both rotates and slides, never does either this or that. Given the speed of sliding, we know the speed of rotation; given the speed of rotation, we know the speed of sliding. Just geometry.

2.4. What Parts To Move Together With Them?

If a movcon is moving, this means an LDraw part is moving. When changing the position of a part, the LMPL system sends a message to the LCD system telling what part was moved and where, and the LCD system, knowing what parts is this part connected to, moves those parts along with it, too. After moving these ones, it takes all parts connected to them, and so on, as long as there is any part to be moved.
  A part connected to a moving part will be moved only if their connection is a firm one. A connection is firm, according to a given movement, if that movement shall take that connection together with itself and move it.
  For example, a Stud–Stud Inlet connection, not being a movcon, is firm in all circumstances: if a Brick is moving and there is another Brick connected to it with a Stud–Stud Inlet connection, that second Brick will move together.
  On the other hand, a part connected to a moving part will be left where it is if their connection is a free one. A connection is free, according to a given movement, if that movement shan’t take that connection together with it and shan’t move it.
  Unfortunately, this won’t be so much comfortable always. A connection what isn’t a movcon will be a firm connection in all circumstances, but a movcon may be firm or free, depending on the movement. For example, take an Axle going through a Brick with a Pinhole. If the Axle is sliding along itself, the Brick will stay where it is, because the connection is free in this case. But if the Axle moves in any other direction (being made to do so by another moving part connected to it), the Brick will go together with it, because the connection is now firm.
  It is beyond our capabilities and intentions to develop a full algorithm to detect when will a movcon be free or when will it be firm. But to develop this algorithm is a key problem to make LMPL working.

2.4.1. How to Follow YUMMY? And What Is YUMMY, For Minifig’s Sake?

In an LCD model, each part is registered as connecting to several other parts, and these parts are registered as connecting to several other parts, too, including the part we have taken. That is, if we put two Gears together and begin to rotate the red one, this will force the LMPL system to search for parts connecting to it; so it will find the blue one and rotate it, too. But this makes the LMPL system to search for parts connecting to the blue Gear, so it will find the red one and rotate it, too. And so on, in an endless loop. Endless loops with no exit aren’t the favourite pets of programmers.
  To avoid this problem, we establish a strict law, obligatory for all moving parts: YUMMY – You Mustn’t Move Yourself. This means that when looking for connecting parts, we won’t take any part twice.
  How to do this? In the execution of a given LMPL movement command, we take the part which the command had been sent to, and apply a note to it: we set a flag in its properties called Yet Seen. This means we have seen that part. And when applying our movement to all parts, one by one, we set their Yet Seen flags as well. For example, take the crane truck already mentioned, and let’s suppose we give it a command to go forward. This means that a pair of wheels receive a command to rotate. As mentioned in section 2.3., a Wheel–Surface connection is moving by rotating the Wheel and making it slide at the same time, so the Wheel will slide forward. The Axle is connected to the Wheel, and the Axle Holder is connected to the Axle, and there is Plate 1 and Plate 2 connected to the Axle Holder, and Plate 3 is connected to Plate 1, and Plate 2 is connected to Plate 3, but stop! we have already dealt with Plate 2, its Yet Seen flag is on. So we go on with Plate 4 connected to Plate 3 and so on, as long as there is any part connected to a moving part with a firm connection and having a Yet Seen flag unset. If done with this, we clear the Yet Seen flags for all parts, to make clear room for the next movement command.
  The properties of a part (not kept in the parts’ inventory but built in an LDraw scenario) include movement assigments. When applying a movement command to a part, we record the movement in the properties of that part, set its Yet Seen flag and go on; no actual movement is done yet. Later. The properties about movements contain the following information:
  a) what direction does that part sliding to, with what speed, until what end condition;
  b) what axis does that part rotate around, what direction, with what speed, until what end condition.
  Points a) and b) may be repeated several times, to cover movement coming from several sources.
  There are three main kinds of end conditions:
  a) endless movement (i.e. until a stop command issued by the user);
  b) until a given state is reached;
  c) inherit of kind b).
  Kind b) may be of several types, such as: “slide to a given distance”, “rotate by a given angle or number of rotations”, “slide until a given coordinate is reached”, or even “until part number x reaches a given position relative to part number y”. This depends only of the level of sophistication, not to be dealt with here. (See later in section 2.7.1.) But kind c) is an important thing.
  When applying movement to a model, we register the given order of movement (such as “rotate by 360 degrees”) only to that very part the order is given to. For all other parts connecting to the aimed part or connecting to those parts etc., we only state the end condition as “keep moving until part number x stops”, calling the aimed part by its unique identifier. Such identifiers may be, for example, Brick116 or Bushing419, given by the system automatically; but the user may rename any part.
  The reason is obvious. If we push a car forward with an inch, we may almost be sure that all parts of it will come an inch. But if our command says “go forward until you reach that wall”, the system must know clearly which part of the car is ordered to reach the wall. And if all parts would be ordered to make an independent movement, this would lead to unwanted results if some parts finish their movement but other parts are still moving, therefore making the parts just stopped to begin moving again. So, any given movement command assigns an end condition of kind a) or b) to one and only one part, and all other parts receive a kind c) one only.

Note that movement is always blocked by physical contact. Physical contact is simply discovered by the LCD system by checking if two parts are inside each other, not meaning their cavities, if any, but overlapping their “plastic” body. If a movement would result in such a situation, the LCD system rejects the movement. This makes a car not to run through a wall: it stops when its first part touches a part of the wall.
  Physical contact is not tested during building: it is still possible to add furniture to a house by moving parts through the wall. During building, prohibiting physical overlap would simply harden the work. But if the user places a part in a location where it is overlapping with another part, the LCD system gives a warning.

2.5. Where Are Movcons Built In Our Scenario?

This will be registered in the Movcons’ List, mentioned already in section 2.1. The LCD system adds data to this list when creating a movcon; removes data from this list when disconnecting a movcon; and does not do anything else with it.
  But it is very important for the LMPL system. The Movcons’ List (ML for short) maintains a list of all currently existing movcons of our scenario. This list can be viewed by the user, too.
  When creating a movcon, it receives a unique identifier what is readable for humans, too. Note that we register connections, not parts. For example, a Gear put on an Axle makes a movcon named Gear_Axle1 or so (assuming this is the first such connection in the model), adding another Gear to it makes a movcon named Gear_Gear1 etc. Most Gears needn’t to slide on their Axles in real models, but we register all movcons, no matter how important may they be. That’s up to the user to use them or not.
  The user can rename movcons to any unique name such as CraneRotator or so. Also, the user can hide movcons in the ML; this makes them not to be listed here, but all effects are the same. When operating with movcons, the LMPL system does not refer to the ML; the ML is necessary only to give an interface between possible movements and human wishes.
  For multi-model scenarios, we need model identifiers, too. So, a newly created Gear connection in an untitled model is called Model1.Gear_Gear1, nothing less, nothing more. Later, if we change the name of the model (what is different from the description in the first line of the .dat file and different from the file name – it is a Model Name) to, say, PoliceCar, our connections are renamed as PoliceCar.Gear_Gear1 and so. Another model in the same scenario may have connections like AmbulanceCar.Gear_Gear1 and similars.
  Having more instances of the same model in the same scenario, we may call them in the same name, assigning indices. For example, having a race track with three racing cars, we may call the models Car(0), Car(1) and Car(2), making it easier to issue commands; therefore, the connection of their wheels and the surface is called Car(0).Wheel_Surface1, Car(1).Wheel_Surface1 and Car(2).Wheel_Surface1, respectively. [Car(0).Wheel_Surface2 refers to the other wheel pair or the second single wheel of the same car.] Note that the whole naming thing is used to refer to movcons only – having three cars called the above way does not mean that those cars must be identical. It means only that their _movcons,_ or more exactly, their _important movcons_ are the same and acting the same way, or will be being assumed to do so. If we refer only to the wheel–surface movcons, our cars may be any imaginable LDraw creations having the referred number of wheels. If we refer to a steering wheel, they must have a steering wheel, too. If we refer to a crane, they must have a crane. Or, if we issue commands to the crane of Car(0) only, it does not matter if the other two cars have a crane or not.

2.6. Among These, What Are Important And What Are Not?

An important movcon is a movcon what the user wants to do something with. An unimportant movcon is a movcon what the user doesn’t want to use. For example, let’s see set 8020, page 2. Step 1 of assembling creates four movcons, called Model1.Pin_Pinhole1 thru Model1.Pin_Pinhole4. These pins will hold Technic 1 x 8 Bricks forming the outer walls of the vehicle, and in later steps, these walls will be fixed and become unmovable. Therefore, these four movcons can’t do any movement.
  Do we need to remove them from the Movcons’ List? No, because of several reasons. First, it wastes time. Second, an unmovable movcon can become a movable one by removing a part blocking its movement. Third, it absolutely doesn’t matter how many movcons are in the list. The user simply won’t use the blocked ones, or if s/he tries to, there will be no result.
  Another category of unimportant movcons are the unblocked, but simply unused ones. For example, in the next steps of the same model, we begin to build a steering system, what includes several movcons (the model name is omitted here for shortness):
  Step 2: Pin_Pinhole5, Pin_Pinhole6 (Steering Arms with the gray Technic Plate); Pin_Pinhole7, Pin_Pinhole8 (Steering Arms with the horizontal Axle Pins); Axle_Axlehole1, Axle_Axlehole2 (Steering Arms with the vertical Axle Pins).
  Step 3: Pin_Pinhole9 to Pin_Pinhole12 (Steering Arms and vertical Axle Pins with the Technic Plates).
  Step 5: Axle_Pinhole1, Axle_Pinhole2 (the Axle in the yellow Bricks); Axle_Axlehole3, Axle_Axlehole4 (the Axle through the small Gears); Gear_GearRack1.
  Step 6: Pin_Pinhole13 (the Axle Pin in the yellow Brick, shown in the frame); Gear_Gear1.
  We’ve listed here seventeen movcons what are part of the steering system. None of them will become blocked during later building, these movcons will move all when using the steering system. If the model is ready, the user may give a command to Axle_Pinhole1 to rotate, and this will make the whole steering system to operate correctly – but the user won’t do this, s/he will simply take the Wheel put on the roof in step 13 and rotate it. Do we need to keep data about all unimportant movcons and present them to the user?
  Yes, we do. This is a question of simplicity: it is a lot easier to
  include all existing movcons in the Movcons’ List and not to deal with their importance than creating algorithms for their removal. If the user doesn’t want to see them, s/he has the freedom to remove them.

There is a flag in the Movcons’ List called Important, and there is a command in the user interface to toggle this flag. The Movcons’ List can be told to show all movcons, or show only important ones. Of course, being important or unimportant does not change the behavior of a movcon in movements, and commands may be given both to important and unimportant ones. But marking the important movcons in our model will make it greatly easier to automatically create a Dashboard.

2.7. What Commands Can A Specific Movcon Obey To?

A given movcon may obey to several commands, depending on its type. Commands are separated to the following groups:
  1. sliding;
  2. rotation;
  a) one step;
  b) sequence starting;
  c) sequence ending;
  d) sequence pause;
  e) sequence resume.
  That is, issuing a command belonging to group 1a instructs a movcon to slide one step, and stop. Issuing a command belonging to group 2b tells a movcon to rotate continuously.
  Commands may be issued from the Movcons’ List. In this list, any selected movcon can be told to execute a command. Available commands are: slide one step, start sliding, stop sliding, rotate one step, start rotating, stop rotating. For a movcon such as Axle_Axlehole, rotating is forbidden. For a movcon such as Axle_Pinhole1, mentioned in the previous section as of built in the first model of set 8020 in step 5, sliding isn’t forbidden, however this movcon can’t slide in this situation, its way is blocked by Gears; but it would be hard to determine this, so the system checks the possibilities of the movcon itself, and an Axle_Pinhole movcon can slide in itself. But of course, if the user sends a slide command to Axle_Pinhole1, there will be no result, movement is blocked.
  Issuing a command needs parameters, too. There are three kinds of parameters:
  a) who moves;
  b) movement parameters;
  c) end conditions.

“Who moves” means which part will move. For example, take a Technic Brick connected with an Axle. It is absolutely not equal if the Axle begins to slide in the Brick or the Brick starts to move along the Axle, but calling by name, it is the same Axle_Axlehole connection. The Who Moves parameter calls the moving part with its unique identifier.

Movement parameters are, for a sliding command, the direction and speed of sliding. Most slidable movcons can slide in one dimension only, e.g. an Axle_Axlehole may slide northwards and southwards, and no any other way. But there are two dimensional sliders, too: at least one, the Wheel_Surface movcon. Making a Wheel_Surface movcon rotating means the Wheel will rotate and move forward. But if we’d allow this movement only for this movcon, we couldn’t steer an old fashioned car with no steering built. A Wheel may slide, therefore, on a Surface to any direction, not affecting its rotation.
  Movement parameters are, for a rotating command, the direction and speed of rotating. Most rotatable movcons can slide in one dimension only, e.g. a Wheel around its axle. But there are several movcons what can rotate freely in a spherical way: a Towball, for example, can do this, up to a limited angle.

End conditions are the most complex parameters. A one step movement does not require an end condition: it simply instructs the movcon to make a small movement and stop. (This will be very useful during building, to test movement abilities.) Nor a sequence stop command require an and condition: this instructs the movcon to stop its continuous movement, however its given end condition is yet unreached. But a sequence start command needs an end condition.

2.7.1. End Conditions

Making it possible to start a movement with an appropriate end condition is the key for perfect animation. Therefore, we must be careful to collect a comprehensive listing of end conditions. Endless

Endless movement is endless. That’s all, folks. An endless movement may be stopped either with a sequence stop command sent to the moving movcon itself, or with a global command telling “Attention! Stop, you all!”
  On the other hand, endless movement may end without a user action, too. If any of the movcons, moving together with the initiating movcon in the same model, report that its movement is barred by any obstacle and refuses to move, this cancels the whole movement. The movcon cancelling the movement may be the same what is running it: for example, a slide given to an Axle in a Pinhole will end when the next step would disconnect them. Till Time

Till time tells a movcon to start an endless movement, and when a given time has been elapsed, stop it (if it wasn’t already stopped by obstacle, of course). A given time may be a time of the hour (“run this car and stop at 3:40pm”) or may be a given number of ticks. A tick is the smallest time unit what the software can handle. Up To Position

Up to position tells a movcon to move until a given part (called by unique identifier) reaches a position (explained by a coordinate pair, specifying a cubic area in the workspace). This position may be absolute (the same place regardless of changes in the workspace) or relative to a given part (called by unique identifier).
  For example, if we want to send a car to a house, we may give its wheel a rotation up to position command, selecting the area around the house. It is absolutely unimportant if the car is facing to the opposite direction and/or there are blocking objects on the way. If it receives the appropriate steering commands during its way, it may find the house and stop.
  A relative command may be useful, for example, when moving parts of models. Having a fire brigade truck with a turnable arm, we may rotate it by selecting a part of the arm, and telling that this part must reach a position relative to a part of the body. In this way, it doesn’t matter if the car is running or stopped. Up To Distance

A variation of up to position, up to distance compares the distance of two selected parts, and stops movement when they are closer than the given distance, farther than the given distance, at the given distance, or not at the given distance, respectively. Ping-Pong

Ping-pong is not an end condition, it is a flag applicable to any end condition. It tells the system to start a reverse movement if it is stopped by any cause, not including user request.

2.8. Communication Between Movements

In a scenario with at least two movcons what are independent from each other, a need will arise to make some contact between their movement. For example, two cars meet at a road crossing. Both stop. One of them starts again and crosses the way. The other one waits until the partner is over, then starts, too. How to make such a movie most easier?
  There would be a way, of course, to instruct everything on our own, but five cars are enough to become tiring, and there are other things, not only cars in a nice Legoland town to be dealt with.
  Therefore, we need communication between movements. This will turn chaos into order.

2.8.1. Movement Identifiers

As well as for parts and movcons, we will have identifiers for movements, too. For example, if part Model1.Gear1 and part Model1.Gear2 form a movcon called Model1.Gear_Gear1, and we start this movcon to move, this movement will be called Model1.Gear_Gear1.Movement. Of course, we may rename the whole thing to, say, ClockRotation. They have another identifier, too, what is hidden for the user and is entirely numeric: this ensures the link between movcons and movements be kept. (This is the case also for movcons: they have a hidden numeric identifier, so we may give them any name, they can keep the link with the parts forming them.)

2.8.2. Durings

A “during” is a command sequence to be executed during a movement. The user may give durings to any movement. A during consists of two parts:
  a) when to do;
  b) what to do.
  For example, the user may start a car by making its Wheel to rotate, and equip this movement with a during telling to turn the steering wheel every ten second. When To Do

A when to do condition makes the what to do part of a during to be executed. This condition may refer to things about the movcon or its movement itself, or to absolutely different things.
  There may be more than one conditions in the same during, and they may lead to the same action or to different ones. Every Nth Tick

This tells to execute every Nth tick. For example, it is a good idea to tell a car to watch continuously if a minifig is before it. On Movement State

This tells to execute if the state of a given movement is at a given value. For example, a gear responsible for the hour-hand in a clock may examine if its rotation is equal to 30, 60, 90 etc. degrees. If yes, it may start a movcon to pop up the cuckoo.
  The referred movement may be a different one, too. For example, a wheel movement in a car may examine if the rotator of the nearby railway barrier is working to lower the barrier. If yes, the car should stop.
  A state may be:
  a) Is there sliding in the movcon?
  b) Is there rotation in the movcon?
  c) Is the distance of sliding in the movcon less than, equal to, greater than, less than or equal to, greater than equal to, not equal to a value?
  d) Is the angle of rotation in the movcon less than, equal to, greater than, less than or equal to, greater than equal to, not equal to a value? On Position

This tells to execute if a given part is at or not at a given position, absolute in the workspace or relative to another given part. For example, the car may stop if seeing the railway barrier being down, or the train may stop if seeing a minifig on the rail. On Distance

This tells to execute if a given part is closer than, farther than, at, close or at, farther or at, or not at a given distance to another given part. For example, the wheel of a car may stop if its right (in Britain, left) front light is one centimeter away from a stop sign. Or, when the distance of any two parts of any two cars is zero, the wheel of an ambulance car may start rotating… On Variable

This tells to execute if a given system variable has a value less than, equal to, greater than, less than or equal to, greater than or equal to, or not equal to a given value. System variables may be used to cover circumstances what cannot be determined just by movement, position and distance examinations. For example, it is absolutely not equal if a car hits the first or the tenth minifig… Idle

Idle is a flag telling what time can the during be activated. It has one of four values:
  a) when moving;
  b) when idle;
  c) both moving or idle;
  d) neither.
  Additionally, there is an IdlePause flag telling if
  a) paused state counts as moving;
  b) paused state counts as idle;
  when evaluating the Idle flag.
  All movements have their own Idle and IdlePause flag.
  For example, a Gear may invoke commands from its during when it is rotating, but it may do so even when it isn’t rotating at all. Idle execution is usable to make movcons to wait for given circumstances, and start only that time. For example, the Wheel of a police car will be moveless until another car hits a minifig. What To Do

If the when to do conditions of a during are valid, we execute commands. These commands may alter the movement of which they are belonging to, alter other movements, change variables or make other changes. Start, Stop, Pause, Resume

Starts, stops, pauses or resumes a movement. The movement is described elsewhere, the only thing to do is calling it by name.
  The difference between stopping and pausing is that pausing does not clear the command given to the movcon. If a movement has been stopped, the movcon forgets everything and needs another movement command to be given it. If it is paused only, the movement can be resumed from the same state. Change

Changes one or more parameter of a movement. This may be the direction, the speed, the angle, or even the end condition. Of course, if a during assigns a new end condition to a movement, it doesn’t matter if that end condition was already valid in the past. Set, Increase, Decrease

Sets a system variable to a given value or increases or decreases it by a value. Initialization Commands

Any command available in the initialization section (see section 2.9.) is available in a during, too. For example, models may change their initial grouping (see section 2.10.) during runtime. Build, Destroy, Restore

Commands usable for building or destroying models during runtime. The Build command creates a new part, what wasn’t previosly existing in the workspace. It needs
  1. a new unique identifier for the part;
  2. a new or existing model name;
  3. a type identifier (e.g. 3001 for the Brick 2 x 8);
  4. a color identifier;
  5. a) position and rotation values;
  6. a) autoconnection allowance;
  5. b) a unique identifier for an already existing part;
  6. b) a description on how to connect to the part written in 5. b).
  Using position and rotation values to place the part with autoconnection (using the LCD system) turned off is discouraged. It should be used only to start new models, not connecting to any existing models.

Destroy removes a part or a group, but doesn’t remove them from memory. They will be invisible, inactive and they can’t obstacle movements. But they can be restored with a Restore command if their place isn’t occupied by other, newly built parts. Disconnect, Connect

Disconnect makes two parts to be disconnected. For a movcon, this removes it from the Movcons’ List and clears its name. Its during, if any, is cancelled from processing. The parts forming the connection will remain where they were, but no longer connected. If the LCD system tends to reconnect them automatically, there may be a flag applied to mark not to connect these parts.
  Disconnecting makes it possible, for example, to make a minifig get off from a car, or a car to jump up the air.

Connect makes two parts not connecting to be connected. If it isn’t a movcon, no name is required, since unmovable connections don’t have a name. If it is a movcon and there is no name, the system gives it a name automatically, as well as during building. If there is a name specified, it may be the name of a previously disconnected movcon. If so, the properties and the during of the disconnected movcon are inherited by the new movcon. Save, Load, Revert

Save saves the current state of the workspace to a disk file, including the state of all parts, movcons, system variables, user defined names, groups etc. Load loads this state back, overwriting changes made since.
  Revert sets the workspace back to its initial state: moves models back to their inital place, movcons to initial state, system variables to initial values etc. Add Model, Remove Model

Adds or removes a model. To add a model, it has to be built already, and be stored in a disk file or present in the scenario. In the latter case, we have to identify the model to be copied and a new name for the added model. In both cases, we have to tell where to place the model and what rotation.
  Removing a model means to make it be forgot for later execution. Only a Load or a Revert command can take it back.

2.9. Programming

Having a scenario built, we may make it moving two ways: either with a single command or with a longer program. Using a single command is easy and makes something moving immediately. Running a program is more difficult, but may lead to more complex and enchanting situations.
  An LMPL program is made of several parts:
  a) an initialization section;
  b) movement descriptions, including an optional General Process;
  c) user procedures and functions.

2.9.1. The Initialization Section

A program begins with an initialization section what is responsible for setting several initial values and options, if any. These settings are used when our program begins to run.
  The initialization can do the following:
  a) clear the workspace;
  b) load models and place them in the workspace;
  c) rearrange loaded models and movcons;
  d) set system variables;
  e) set grouping;
  f) change Dashboards;
  g) send commands to movcons to start initial movement. Clearing The Workspace

Clearing the workspace with a user command removes all LDraw parts from the workspace and, optionally, delete any LMPL code stored. Clearing the workspace from the initialization section of an LMPL program cannot delete LMPL code, since this would mean deleting itself; therefore, clearing the workspace from an initialization section removes any LDraw part left in the workspace and nothing more. This ensures that there will be no models in the workspace before loading models from the same initialization section. Loading Models And Placing Them In The Workspace

A model may be put in the workspace two ways: either by being built there or being loaded into it. When the user builds a model, s/he can save it alone to a file what contains nothing more than the model, similar to currently available dat files. (The only difference is that also LCD information is being stored in it.) When the model is saved, it may be removed from the workspace and a new model may be built; or the user may keep several models in the workspace and make changes on them.
  Loading models from the initialization section ensures the workspace to be in a required state, most likely if the workspace was cleared previously. Rearranging Loaded Models And Movcons

Rearranging means moving models to a given position and turning them to a given direction; setting movcons to a given state, i.e. to set all properties to the values the user wants to. Changing the position a movcon is being in is done by sliding or rotating the movcon (in invisible mode) until the required position is reached, so the whole model will react on the change.
  Rearranging models from the initialization section ensures the workspace to be in a required state, no matter what state were the models saved with. Setting System Variables

Setting system variables gives initial values to the variables before the process starts. Setting Grouping

Setting grouping makes grouping (see section 2.10.) to be in a required state before the process starts. Changing Dashboards

Changing Dashboards from the LMPL program (in the initialization section or later from a during) can be useful to make Dashboards reflect on changes done in the workspace. See section 2.11. Sending Commands To Movcons To Start Initial Movement

Sending commands to movcons is necessary to make any initial movement to start automatically. At least one command from this category is needed in the initialization section; otherwise, the Start command will return control to the user in a moment, with no movement done.

2.9.2. Movement Descriptions

A movement description is a separate section describing a movement. It is, in fact, the during description, detailed in section 2.8.2. The General Process

The General Process is a special movement description which does not belong to any movcon or any model. It is self-supporting and belongs to the workspace.
  If the program contains a General Process – what is not obligatory –, it starts immediately when the program is started and runs continuously till the end. The General Process consists of the same when to do and what to do parts described in section 2.8.2.
  If the program doesn’t contain a General Process, animation runs as long as there is any movcon being in movement. If there is a General Process, all movcons may be stopped without stopping the animation – it stops only if the end condition of the General Process is reached. But if so, the animation is terminated, no matter if there is any movcon in movement or not.

2.9.3. User Procedures And Functions

User procedures and functions are sections containing LMPL code. They may belong to several scopes:
  a) to the workspace (global);
  b) to a model;
  c) to a movcon.
  This is recognized by their name. A procedure or function belonging to a movcon begins with the name of the movcon, e.g. Model1.Gear_Gear1.RotationCounter. A procedure or function belonging to a model begins with the name of the model, e.g. Model1.Driver. A global procedure or function does not have any scope identification, e.g. DisplayHits.
  A function returns a value and may be substituted at any place where a value is required; a procedure does not return a value and can be called as a command.
  Both functions and procedures may be called with parameters; these are always formal parameters. A parameter may be a numeric or text value, or an identifier of a part, a movcon or a model. The functions and procedures may take actions on parts, movcons or models given them by parameters, and these actions are performed as if being done directly without procedures or functions.

2.10. Grouping

Grouping is an important concept in LMPL. In a complex scenario, there are lots of things (parts, movcons and/or models) having something in common but being different in whole. For example, if it is a town with ten cars running on the streets and a hundred minifigs walking around, it would be hard to tell cars to stop when a minifig is crossing way before; but if this is possible (and it is) without grouping, it would surely be very hard to select twenty minifigs to interact with the cars and the others not to. Grouping gives a common name to lots of things having nothing in common what would be obvious for the system, but having something in common for the user.
  Grouping related commands are:
  a) creating a group;
  b) adding elements to a group;
  c) referring elements in a group;
  d) removing elements from a group;
  e) deleting a group.
  Adding and removing elements requires searching for elements, too.

Grouping may be useful to create hidden controllers. For example, in a town scenery, we can use parts built in buildings, road signs, street furniture etc. near the corners and intersections – e.g. a brick in a house wall near to a road crossing –: we can take some of such parts, include them in a group and tell cars if they are in a close distance to any part included in that group, they should turn left or right. This makes our cars to change directions without any visible influence.

2.10.1. Searching For Elements

Elements in a group may be: parts, movcons, models. Any group may contain elements from all three categories together. Elements may be added or removed one by one, or more at a time.
  Finding elements one by one is easy: if it is a movcon or a model, it has a name given it by the user. If it is a part, it has a unique identifier, too, what is mostly internal for the system, but can be obtained from a list.
  Calling more elements at a time is a more difficult thing. We may aim all elements what are belonging to a specific type: for parts, this can be their part number (e.g. 3001) or color, or both; for movcons, this can be their connection type (e.g. Axle_Axlehole) or a string contained in their name; for models, this can be a string contained in their name only. Both for parts and movcons, we may limit our search in one or more given models only.
  If searching in a previously defined group, our search is limited to elements included in that group; additionally, we may want to get just parts, just movcons or just models.
  A search for elements returns all elements corresponding to the criteria; not the first one or the last one, but all at once.

2.10.2. Creating A Group

To create a group, we have to give it a name and add at least one element. A name may be any valid LMPL name what isn’t used already.

2.10.3. Adding Elements To A Group

To add elements to a group, we call it by its name and specify what elements to add. If any element specified is already included in the group, it is omitted by addition. An element cannot be contained twice in the same group, but may be included in several groups at the same time.

2.10.4. Referring Elements In A Group

To refer elements in a group, we have several possibilities:
  a) to refer to all elements at the same time;
  b) to refer to any element;
  c) to perform a search in the group.

Referring to all elements is possible when the context allows more elements to be called at the same time. For example, in a Destroy command, we may destroy all elements included in a specific group at once.

Referring to any element is possible when the context allows one element to be called. For example, measuring distance between a part and any element of a group measures the distances between that part and all elements of the group, one by one, and finally returns the smallest distance found.

Referring to the result of a search (described in section 2.10.1.) in the group may be used according the number of the elements returned; if more elements are returned, the result can be used only if the context allows more elements to be called at the same time.

2.10.5. Removing Elements From A Group

Removing elements from a group cancels the membership of the element in that group.

2.10.6. Deleting A Group

Deleting a group removes all elements from the group and frees the name of the group for further use.

2.11. Dashboards

Dashboards are visual interfaces between the user and his or her important movcons. They look like toolbars and contain several tools. These are added automatically by the system and can be altered by the user.
  The most important usage of Dashboards is when there is no LMPL code or when testing it. Using Dashboards, the user can quickly issue often used commands and get visual feedback from the results, even if the models are off screen or too small or the movement is going behind walls.

2.11.1. Tools

A tool is a separate area on a Dashboard, having a link with an important movcon or with a user procedure. There are two kinds of tools:
  a) controlling tools;
  b) indicating tools. Controlling Tools

A controlling tool is something what the user can take an action on, and this issues commands. Controlling tools can be:
  a) pushbuttons;
  b) on/off switches;
  c) slides and potmeters.

Pushbuttons issue a command each time they are pressed.
  On/off switches change state each time they are pressed, and either a property can reflect on this, or the switch can issue a command when turned on and another one when turned off.
  Slides and potmeters can be slidden or rotated, and a property can reflect on this. Indicating Tools

An indicating tool is something what the user can receive visual feedback with. Indicating tools may be:
  a) digits;
  b) bar graphs;
  c) hour hands;
  d) drawing boards;
  e) peekers.

A digit tool is an area where the value of a property is displayed.
  A bar graph is an area where a bar shows the position of a sliding movcon.
  An hour hand is a circle where a hand shows the direction of a rotating movcon.
  A drawing board is an area where LMPL commands may print or draw anything. This makes a freely definable way of feedback.
  A peeker is a monitor screen where a camera shows a segment of the workspace. Such cameras can be placed in the workspace and point to important or difficult-to-reach locations. They can be defined as stable (staying at a point at looking at a point movelessly), stable-following (staying at a point and looking at a part, following its movement) or moving (looking at a part, following it on its movement by keeping the distance from it).

2.11.2. Creating A Dashboard

Creating a Dashboard may be done automatically. If the user has several movcons marked as important in the Movcons’ List, there is a command to create a Dashboard according to this. This command, available both from the menu system and from LMPL code, takes each important movcon one by one and creates a tool according to its type. These tools are controlling, not indicating ones. For example, a Wheel–Surface movcon may receive an on/off switch to start and stop its rotation.
  Dashboards may be created or changed from LMPL code, too, making it reflect on changes in the workspace. For example, if a model is destroyed, its tools can be removed from the Dashboard.

Commands what are used to change a Dashboard from LMPL code can be:
  a) creating a new Dashboard;
  b) removing a Dashboard;
  c) storing and loading Dashboards;
  d) adding tools;
  e) removing tools;
  f) changing tools. Creating A New Dashboard

Creating a Dashboard needs a new name and, optionally, a placement on the screen. There is no limit on how many Dashboards can be present at the same time. Removing A Dashboard

Removing a Dashboard needs its name. Upon removal, everything stored in the Dashboard is lost. Storing And Reloading Dashboards

Dashboards can be stored in files, either one by one or all together. Adding Tools

Adding a tool requires a new name for the tool; its type; its initial settings; and a command to be assigned to it.
  Tools created automatically are named like Dashboard1.Pushbutton1 and so on. Removing Tools

Removing a tool requires its name. Upon removal, all data in the tool is lost.
  There is a command to remove all tools on a given Dashboard. Changing Tools

Changing a tool requires its name and the properties to be changed. There are special commands for indicating tools to change the values shown.

2.12. Cableworks

Cables are defined in the LCD proposal as consisting of end segments and middle segments. In an LMPL point of view, a cable is a chain of movcons. Cables have a physical and a special behavior. The physical behavior is the same for all cables: if a cable is pulled, it can move something. LMPL observes this in the way that there is a movcon where the end of the cable connects to another part; let’s call this movcon 1. If movcon 1 is sliding, the connecting movcon 2 will begin to slide in the same direction; that makes movcon 3 to slide, that makes movcon 4 to slide, and so on. Finally, if the last movcon, where the other end connects to another part, begins to slide, this makes that part to slide, too. Therefore, it is very easy to connect two cars with a yarn and push one; the other one will follow it.
  The special behavior depends on the type of the cable.

Parts of an electric cable have a property to tell if there is power in them. If an end has power, this goes to the neighboring segment and so on, the whole cable contains power in no time. This happens if there is a battery connected to an end of the cable and the user turns the switch on. If there is a motor connected to the other end, notifying that the cable end–motor movcon has power in it, the system starts the motor axle to rotate.
  To make things easier for ourselves, we differ slightly from real physics here. In real physics, a battery is connected to a consumer with two wires, one for the positive end, one for the negative. As taught in school, power starts from the negative end, runs through the consumer, making it working, and runs back to the positive end of the battery. In LMPL, we still distinguish between negative and positive, but don’t go on the connection chain this way. Any electric cable connected to a battery contains power (if the battery is turned off), either positive or negative, and any consumer connected to both a positive and a negative cable begins to operate. If one or both the cables stop having power, consumers stop working. If both cables have the same sign of power, consumers stop working.
  Handling electric power doesn’t need LMPL commands; it needs, beyond the needed training of the LCD system, only some algorithms to transfer power between parts. These algorithms automatically convert power to rotation in motors and power to light in bulbs. LMPL may, of course, give a command to a battery to turn its switch (a battery is treated as a movcon to make this possible), and consumers may, also being movcons, have durings to communicate with other movcons.
  In LMPL, it is possible to make a motor rotate without a battery, since anything movable may be moved with LMPL. In fact, LMPL substitutes the human fingers what can make anything to move. Using a battery and cables make things more realistic, but everything can be done without it, too.

As for pneumatics and optical fiber, the same work is needed. Pneumatic pistons are movcons, and tubes are cables having a property showing pressure. Movement of the piston is translated to pressure changes; pressure values are transferred along the cable; and finally, pressure in the second piston movcon is transferred to movement.
  Optical fibers transfer light. In a Lego CAD software, where parts are drawn simply, this can be modeled with a simple color change. When exporting our scenario to a raytracer, there should be an ambient light applied. Light bulbs are light sources.

Emulating an RCX or other Lego microcomputer is beyond the intentions of the author presently. A real microcomputer emulation would be an algorithm that can run really written RCX programs, what can be downloaded from the web. This would take a lot of work. But with LMPL, we can imitate an RCX instead of emulating it: for example, a robot following a black line on a white surface can be created by using a light sensor, what is a movcon reacting to light; that sets a property in it. When the light sensor changes its state, another movcon controlling the movement of the robot may reflect to it. Wanting to be more realistic, we may build an RCX into our model and connect it properly with the sensor and the motors; and we may put all LMPL code responsible for the control of the robot into the during of the RCX movcon, and we may write our program to respond incoming electronic signs with outgoing electronic signs only, not to intercept the sensor and the motors directly. In this way, the only thing what differs from the real model is the language of the program in the RCX.

2.13. Subtitling

Creating a fully completed animation often needs titles and comments to appear on the screen. Therefore, LMPL has commands to add objects what are not LDraw parts:
  a) in-workspace texts and graphics;
  b) out-workspace texts and graphics.
  In-workspace means a text or graphic to be appear on a transparent plane inside the workspace. This plane can be rotated in 3D just like any LDraw part, and the camera can fly around it. However, it does not interact with LDraw parts. In-workspace objects can be useful to create non-Lego backgrounds and illustrations; such drawings are often used even in official Lego catalogs, too.
  Out-workspace means a text or graphic added to the viewport after creating the image. No matter how does the camera fly around, out-workspace text is always at the same place of the screen. Out-workspace objects can be useful to comment what is happening on the scenario, adding titles at the beginning and between chapters of the story, and so on.
  To create a text, the following are required:
  a) the text string;
  b) a font to be used;
  c) a color;
  d) text properties like italic, bold, underlined etc.;
  e) a 2D position on the screen.
  To create a graphic, the following are required:
  a) an image stored in a file (bmp, gif, jpg or any format);
  b) optionally, a color specified as transparent;
  c) a 2D position on the screeen.

2.14. The Complete Set

The Complete Set is everything necessary to play a given LDraw animation. To make it possible to give our creations to other people to play it, we have to hand over the Complete Set:
  a) the software;
  b) the parts inventory;
  c) the models used;
  d) the LMPL code;
  e) image files used for subtitling, if any.

The software may either be the real LDraw-based Lego CAD software (MLCAD, LeoCAD etc.), or it may be a player version which does not include building and programming facilities but can display LDraw models and make them moving with LMPL code. The player version does not replay an animation file (avi, fli, mov, mpg etc.), its input is the same set of files as for the full version; but not having building and programming facilities, it is much smaller, therefore it saves bandwidth and storage capacity to use it. I encourage developing a player version.

The parts inventory is as the same set of part files as used in the full version; however, when preparing to distribute our creations, it is a good idea to remove unused parts from the inventory. There may be a feature for this purpose; this copies only the needed part files from the inventory to another directory.

Models used are as the same model files as used in the full version. A model file is a dat file referring to part files, but it contains additional LMPL specific information. Model level code (see 2.9.3.) is stored together with the model graphic itself: such code is automatically included in an LMPL program when the model is included in it. Global code is stored in a separate text file.

2.15. Physics

This chapter describes things what are not absolutely necessary to make LMPL working. LMPL would be a very nice and advanced thing without realizing anything mentioned in this chapter – this chapter is only for make a perfect thing more perfect.
  Everything described here is already used in other softwares; for example, car racing simulators, fly simulators etc. There are algorithms known and well developed for each physical addition. There is nothing new in this chapter for programmers; what is new is only to combine it with virtual Lego.

2.15.1. Gravity

Gravity is a force making things go towards the center of Earth. In LMPL, gravity may be useful the make things a little more realistic.
  Without gravity, it is possible to build models with things floating in the air, with no stanchion at all. This is not very realistic. However, this problem can be avoided by users: if they don’t like such unrealistic models, they build stanchions even if parts wouldn’t fall without them.
  Without gravity, several movements are impossible. By examining official Lego models, most probably we could find some ones where gravity is an essential part of their movement. This problem cannot be avoided: if there is no gravity, these models don’t function as they intended to.
  Without gravity, there is no way to implement ballistics.

Gravity, if once implemented, still can be turned off by toggling a switch. To add fun, we can adjust the gravitational coefficient, too; setting it to 22.9 m/s/s makes things fall as if being on the surface of Jupiter, setting it to 1.6 m/s/s simulates the surface of Moon, and setting it to 9.8 m/s/s simulates Earth. To simulate the weightlessness like in space ships, we have to set the gravitational coefficient to zero, but having inertia turned on.
  During building, there is no gravity by default; however, it can be turned on, sometimes this may help building. In this case, the part currently selected is unaffected by gravity, observed as if holding it in our hands.

2.15.2. Inertia

Inertia is a power coming from the inability of things to change the state of movement without a force coming from outside.
  With inertia, a moving part suddenly stopped don’t cause all moving parts connected to it to stop immediately. For example, if a Technic car, having a body built up from flexible connections, suddenly stops, its roof swings forward due to inertia. Any equipment not connected to it in a fixed way swings forward or even fall off from it.
  To simulate this, we can write an inertia handling algorithm. Most probably, no change is required in any properties. When a moving part stops, any part connected to it in a firm way stop immediately; but any part connected to it in a slidable way continues sliding in the same direction, as long as the connection leaves it to. Any part connected to this part in a slidable way acts similarly. Therefore, a part assembled two connections away from the part stopping moves much less than a part assembled ten connections away. When all parts stopped, everything remains in this deformed state.

2.15.3. Tensile Strength

In the case described in section 2.15.2., a Technic car suddenly stopping becomes deformed due to inertia. A real car may not only deform but even fall into parts if running fast enough, then being stopped. This happens because the force given on connections is stronger than the tensile strength of some connections.
  A tensile strength is measured in the same unit as any force: in newtons. In a first approach, we may estimate tensile strengths for several types of connections; a really exact way would require measuring what is difficult to perform. Note that not only movcons have a tensile strength but also unmovable connections do; they may disconnect in a crash, too.
  Having tensile strength well measured and handled, we can run a car into a wall and see it to fall in pieces. Maybe the wall, too.

2.15.4. Ballistics

Ballistics is a set of formulas to calculate the arc of an object thrown away. Ballistics makes sets like catapults working: there isn’t much use in building a catapult if it can’t throw a bullet out. Ballistics makes it possible to run cars onto slopes suddenly ending and then jump.
  To implement ballistics, we need both gravity and inertia. Without gravity, there is no ballistics; without inertia, there is no throwing.

2.15.5. Weight

Weight is the strength gravity is pulling an object with. Weight is important for several purposes.
  Without weight, a large and complex model falling doesn’t suffer much more damage than a small one.
  Without weight, a car quickly running into a small single part, laying on the surface with no connection, would stop instead of pushing the obstacle away.
  Without weight, several sets like a teeter-totter can’t work.
  Without weight, ballistic computations give false results.
  To implement weight, we have to register weight for each type of part, and summarize it at points. For example, in a teeter-totter, we receive the weight on an end by adding the weight of the parts above it.

2.15.6. Center Of Gravity

Center of gravity is a point where gravity is acting on an object. To implement center of gravity, we need to implement gravity and weight.
  If we know center of gravity, we can build models needing correct balancing. We can recognize if a model is slanted too much to make it tip over. When a model is stanchioned only at one end and a large weight is above the other end, we can recognize this and make it to tip over or disconnect in the stanchioning if there is not enough tensile strength. This is called statics.

3. Language Syntax

In this chapter, I describe a proposed syntax for LMPL code. This syntax is arbitrarily chosen and may be altered in a real implementation to make things easier either or both for the developer or the user.

3.1. Syntax Notation Conventions

In this chapter, the following notation conventions are used:

  Words written in uppercase denote keywords what mustn’t be changed. In actual use, processing code is case-insensitive.
  Words written in lowercase denote placeholders. A placeholder should be substituted with an appropriate value. Values may be constant values, variables, functions or expressions combinating these.
  [ ]
  Anything written between brackets is optional. Brackets must not be typed.
  … An ellipsis denotes a list can be continued as long as necessary.
  { | } Things between braces and separated by vertical lines denote items the user has to chose one of.

3.2. Language Basics

LMPL language is a language based on modern BASIC conventions. This was the most appropriate chose for a language with such a purpose, because
  – it is easy to learn and quick to use, not requiring lots of declaration and dimensioning, and having a flexible syntax;
  – it is easy to be realized by programmers, not requiring lots of workaround;
  – the purpose of the language creation does not require neither a very high nor a very low level language.

The building elements of LMPL code are sections and commands. Commands are consisting of a command keyword and optional parameters. Parameters can be constant values, variables, functions or expressions combinating these.

3.2.1. Data Types

Data types are the categories data are classified into. Any data must be classified as belonging to a data type to make it possible to handle it. Each constant, variable and function belongs to a data type, and only to one data type each.

Numeric. Any number is a numeric type. A numeric type constant may look like 3 or -37475.668 etc. In most languages, there are several numeric types such as integer, floating point and so on. In LMPL, further research may discover if there is need for distinguishing several numeric types, and if yes, what types are required. Our current point of view is that one numeric type is enough, if providing a large scope of values (i.e. there is a large scale of numbers between the smallest and the greatest allowed value) and decimal digits are allowed. Decimal digits are necessary for computations such as sine and cosine, what play important role in movement representation. Therefore, an integer type may not be enough.
  In program code, a numeric constant is represented by a word
  consisting of:
  [{+|-}] = an optional sign mark, what can be either + or -
  [digit[digit…]] = an optional digit followed by one or more digits
  [.digit[digit…]] = an optional decimal point followed by one or more digits
  Digits are optional because a valid constant may be written as 3 (with no decimal point and no decimal digits) or .5 (with no integer digits). However, at least one digit is required on either side of the decimal point.

String. A string is a series of characters. Each character is a value treated as a value representing a letter, number or punctuation mark, corresponding to a code table. To keep up with the century, let me suggest Unicode as a code table, having each character encoded as a 16 bit value. However, most developing tools don’t support Unicode yet, or not well enough, so if this makes a problem, it won’t worth it to fight for it against technical limitations. Seemingly, strings don’t play a key role in LMPL.
  In program code, a string constant is represented by:
  Explanation: one or more characters between double quotation marks, or even no character between them; this latter case represents the empty string. The constant may not contain any quotation mark; to include it, we have to refer it by a function.

Part. A part is a data pointing to a part what is built into our
  current scenario. In realization, a part may be a string looking like "P16", meaning it is the 16th part placed in the scenario. Properties of the part can be found in the list of parts, at index 16.
  In program code, most times there is no constant part reference. Instead, we refer to them by part names like Model1.Gear5, what is really a variable containing "P16" as a value.

Part Type. A part type is a data referring to a type of parts, e.g. a 3001 Brick 2 x 8. In realization, a part type is a number as like as 3001.
  In program code, part type is used simply by specifying the number of the part type, such as 3001.

Color. A color is a data pointing to a color. In realization, color is a number which selects the color on a palette. Possible palettes are: LDraw palette (default) and RGB palette. An RGB color is created by a three-byte value containing each color ingredient in a byte.
  In realization, most times there is no constant color reference. Instead, we refer colors of the LDraw palette by color names, what are really variables containing appropriate numbers as values.

Movcon. A movcon is a data pointing to a movcon what is built into our scenario. In realization, a movcon may be a string looking like "C42", meaning it is the 42nd movcon built in the scenario. Properties of the movcon can be found in the Movcons’ List, at index 42.
  In program code, most times there is no constant movcon reference. Instead, we refer to them by movcon names like Model1.Wheel_Surface1, what is really a variable containing "C42" as a value.

Model. A model is a data pointing to a model what is built into our scenario. In realization, a model may be a string looking like "M5", meaning it is the 5th model built in the scenario. Properties of the model can be found in the list of models, at index 5.
  In program code, most times there is no constant model reference. Instead, we refer to them by model names like Model1, what is really a variable containing "M5" as a value.

Dashboard. A dashboard is a data pointing to a Dashboard what is built for our scenario. In realization, a dashboard may be a string looking like "D6", meaning it is the 6th Dashboard built for the scenario. Properties of the Dashboard can be found in the list of Dashboards, at index 6.
  In program code, most times there is no constant Dashboard reference. Instead, we refer to them by names like Dashboard1, what is really a variable containing "D6" as a value.

Tool. A tool is a data pointing to a Dashboard tool what is built for our scenario. In realization, a tool may be a string looking like "T21", meaning it is the 21st tool built for the scenario. Properties of the tool can be found in the list of tools, at index 21.
  In program code, most times there is no constant tool reference. Instead, we refer to them by names like Dashboard2.Tool6, what is really a variable containing "T21" as a value.

Object. An object is a data pointing to any other object what is built in or around our scenario. In realization, an object may be a string looking like "O63", meaning it is the 63rd object built for the scenario. Properties of the tool can be found in the list of object, at index 63.
  In program code, most times there is no constant object reference. Instead, we refer to them by names like Camera5, what is really a variable containing "O63" as a value.

3.2.2. Names

Any data of any type may receive a name to identify it. Names are pointers pointing to the value they are substituting. A name must conform to the following regulations:
  – it must begin with a letter;
  – it can contain the following characters: letters, digits, dots (.), underscores (_);
  – it can be of any length with no upper limit;
  – it must be unique in the system.
  Giving a value to a name overwrites the value stored in that name previously. Default Names

Creating a movcon, a model, a Dashboard, a tool or an object implies creating a name for it to be called with. These are default names.
  A default name for a model is Model1, Model2, Model3 and so on.
  A default name for a movcon begins with the model name and a dot, and an identifier for a movcon based on its type. For example, Gear connections in Model1 are called Model1.Gear_Gear1, Model1.Gear_Gear2 and so on; Gear connections in a model renamed as Robot are called Robot.Gear_Gear1 and so on; Towball connections in a model named as Train are called Train.Towball1, Train.Towball2 etc.
  A default name for a Dashboard is Dashboard1, Dashboard2 etc.
  A default name for a tool begins with the name of the Dashboard and a dot, and an identifier for the tool based on its type. For example, digit tools are called Dashboard1.Digit1, Dashboard1.Digit2 and so on; peeker tools on a Dashboard renamed as Monitoring are called Monitoring.Peeker1, Monitoring.Peeker2 etc.
  A default name for an object is based on the type of an object. For example, cameras are named as Camera1, Camera2 etc.

Default names may be changed in two ways. First, any name may be copied into another name, this is true both for variables and for models, movcons etc. For example, issuing an assigment command like MyCar = Model1 makes all further commands referring to MyCar act on Model1 in real. But newly created movcons in Model1 are still called Model1.Motor1 and not MyCar.Motor1.
  Second, any name may be renamed. Issuing a rename command like
  RENAME Model1 AS MyCar
  makes all further command referring to MyCar act on what was previously Model1. Newly created movcons are called MyCar.Motor1. In fact, there is no thing called Model1 after this command. A newly created model may receive Model1 as default name again.
  It is a good idea to keep a global list of names in the system, including all movcon, model and variable names etc. together with their values. If so, a rename operation can be allowed even on a variable, what makes the previous name obsolete. This is untraditional in programming but nothing bad would come from it.

3.2.3. Groups

Groups are something similar to arrays in other programming languages, but in fact they are different. Arrays contain indexed elements, and elements can be reached via their indices only. Arrays may be of one or more dimensions. An array can contain data of the same type only. Groups don’t work so.
  A group is a list of values. It may be indexed, but indices are of less importance. A group can contain any elements, no matter what data type are they belonging to. For example, a command like
  ADD Things Myhouse, Robot.Gear_Gear3, "Hello", TopCamera, 3+3
  results in an entry in the list of groups, where the name is Things and the value is somewhat like the following:
  "M6" "C117" "Hello" "O29" 6
  because the names are translated to these values. As shown here, even constants may be stored in groups.

To refer to a group, we use its name. To refer to one or more elements, we use this syntax:
  groupname(element[, element[…]])
  where element is any valid element classificator.

3.2.4. Arithmetics

Arithmetical computations are the key in all programming, no matter what purpose is it done for. When controlling LDraw models, we may need arithmetics to discover, for example, how often to turn a steering wheel to make a car to follow a path.
  Arithmetical expressions are consisting of the following elements:
  a) values;
  b) operators;
  c) parentheses. Values

A value is a constant, a variable or (the result of) a function. In arithmetic expressions, we have to distinguish between numeric and string values, because "Hello" / 3 has not much of sense. This can be done when evaluating an operator: if the operator receives values of different type and it isn’t an operator what could handle it, an error occurs. Operators

An operator is a sign or word between values intended to do something with them. Valid operators are:

First level

Powering. Raises a number of a power, e.g. 2

Second level
  / Division. Divides numbers, e.g. 6 / 4 gives 1.5.
  DIV Integer division. Divides numbers resulting in an integer, e.g. 6 DIV 4 gives 2 (rounded).
  * Multiplication. Multiplies numbers, e.g. 2 * 4 gives 8.

Third level
  + Addition. Adds numbers, e.g. 3 + 3 gives 6.
  - Subtraction. Subtracts numbers, e.g. 6 - 3 gives 3.
  + Concatenation. Concatenates strings, e.g. "A" + "B" gives "AB".
  MOD Modulus. Gives the remainder of a division, e.g. 6 MOD 4 gives 2.

Fourth level
  = Equal. Compares values, e.g. 3 = 3 gives true.
  < Less than. Compares values, e.g. 3 < 3 gives false.

Greater than. Compares values, e.g. 3 > 2 gives true.

<= Less than or equal. Compares values, e.g. 3 <= 3 gives true.

= Greater than or equal. Compares values, e.g. 3 >= 4 gives false.

<> Not equal. Compares values, e.g. 3 <> 3 gives false.

Operators are evaluated in the order of levels, beginning with the first level. Operators from the same level are evaluated from left to
  right. Parentheses

Parentheses can be applied to change the order of evaluation in an expression. Parenthesized parts take precedence over parts outside the parentheses. In LMPL, three kinds of parentheses can be used: () [] {}. All three have the same meaning. The type of the opening and the closing parenthese of a pair must be the same.

3.2.5. Code Sections

LMPL code is separated into several sections. A section consists of a header, a text (commands to be executed in the section) and an end mark. A header is always formed as a line looking like
  sectiontype [sectionname [(parameters)]]
  where sectiontype is a keyword telling what type of a section it is, e.g. for a procedure we use the keyword PROC. Sectionname is the name of the section; some special sections don’t have a name at all. Parameters specify an optional list of parameters. Section Types Initialization Section

The initialization section is executed when the program starts. Each model may have its own initalization section and the general program may have its own one; execution begins with such sections of each modules, then the general initalization section, therefore making it possible to override model-specific settings in the main program.
  An initialization section of a model looks like:

INIT modelname


A general initialization section looks like:



Initialization sections don’t have parameters. There is no way to call initialization sections from program code, they are executed only once each time a program is starting. Durings

A during is a section to be executed while a movcon is moving, or if the Idle flag is set so, while it isn’t moving. A during section looks like:

DURING movement


where movement is the name of a movement (see section 2.8.1.). This is a required parameter. When starting a program, Idle and IdlePause (see section are given to their default settings, Idle is set to moving (executing durings only during moving), and IdlePause is set to false (during pause, no execution). To change these settings, we can use commands. To change them just when the program is started, we can place such commands in the initialization section.
  Issuing a Pause or Stop command for a during pauses or stops its movement, therefore affecting the execution of the during.
  During sections don’t have parameters. There is no way to call durings from program code directly, but we can make them run or stop by putting the movement they are belonging to in the appropriate state. General Process

The General Process (see section is a special during which always starts first after execution the initializations, and is always running while the program is running. It looks like:



Issuing a Pause command for the General Process pauses the entire Lego CAD application. Issuing a Stop command for the General Process terminates all movement and puts the application back to building mode. In the player version (see section 2.14.), issuing a Stop command for the General Process terminates the application and gives control back to the operating system. User Procedures And Functions

A user procedure or function can be created for a task what is common in the program, not concerning for any specific movcon or model. For example, in a game, there can be a procedure to display current score, check for remaining lives, perform specific animations and so on. Additionally, these are the only sections what can be called from other sections, therefore, being able to be executed in any situation.
  Any code applicable in a during can be used in a user procedure or function, too.
  A user procedure looks like:

PROC procname [(parameters)]


A user function looks like:

FUNC funcname [(parameters)]


The difference between PROC and FUNC is that a PROC cannot return a value but a FUNC can. To return a value, we have to use a command like
  funcname = value
  in the FUNC section.
  To call a PROC, issue its name as a command, providing appropriate parameters:
  procname [parameters]
  To call a FUNC, issue its name as part of an expression, providing appropriate parameters:
  funcname[(parameters)] Parameter Lists

Parameter lists are lists of placeholders for parameters of sections. The only section what can have a parameter list is a user procedure or function.
  A parameter list in the header of a section looks like:
  [(placeholder[, placeholder […]])]
  meaning that there can be one or more placeholders, separated with commas, between parentheses, but the whole thing is optional.
  A placeholder is a name used to refer the value given to the section. This is a formal parameter. For example, if we define a procedure with this header:
  PROC MyProc (MyPara)
  and we call it from elsewhere with the command
  MyProc 100
  this will create a variable called MyPara, containing a value of 100, available during executing MyProc. When MyProc is done, MyPara is deleted; when calling MyProc again, MyPara is recreated with another value.
  If we have another procedure defined with this header:
  PROC MyProc2 (MyPara2)
  and we call it from within MyProc with the command
  MyProc2 200
  this creates MyPara2 as well, but makes MyPara inaccessible for MyProc2. MyPara is accessible only from within MyProc, being a parameter of it.
  To clear things, let’s create a sketch:

   [here, both MyPara and MyPara2 is undefined]
  MyProc 100
   [here, both MyPara and MyPara2 is undefined]

PROC MyProc (MyPara)
   [here, MyPara is equal to 100, MyPara2 is undefined]
  MyProc2 200
   [here, MyPara is equal to 100, MyPara2 is undefined]

PROC MyProc2 (MyPara2)
   [here, MyPara2 is equal to 200, MyPara is undefined]

When calling a user procedure or function, formal parameters are substituted by the values given. Substitution begins with the first value and goes on, left to right, until all values are assigned to parameters. For example, if the header looks like:
  PROC MyProc (Para1, Para2, Para3, Para4)
  and we call it with a command like:
  MyProc "one", "two", "three"
  this makes Para1 = "one", Para2 = "two", Para3 = "three" and Para4 to be undefined. If there are more values given than parameters specified, needless values are dropped.

Parameter lists may contain a LIST keyword to specify a list of values with variable length. For example, a section header may look like:
  PROC MyProc (SingleValue1, LIST ParaList, SingleValue2)
  In this case, SingleValue1-2 are normal values like the ones dealt with before, but ParaList is a list. To call this procedure, we have to give a list of parameters in parentheses:
  MyProc 100, (1, 5, "Joe", Model1.Gear_Gear1), 200
  When starting the execution of MyProc, SingleValue1 is 100 and SingleValue2 is 200; these values don’t change later. And ParaList is equal to 1. Later, after processing this value, we can issue a command:
  STEP ParaList
  This drops the value of 1 and gives ParaList a value of 5. The next STEP ParaList commands drops 5 and assigns "Joe". The third one gives ParaList the value of Model1.Gear_Gear1. Finally, a fourth STEP command finds no further value in the list, so it gives a value of "OVER".
  Variable length parameters may be useful when processing elements of groups one by one, for example.

3.2.6. Additional Syntax Issues

The end of a command is marked by the end of the line. For example:
  a = 1
  b = 2
  are two assignment commands.
  We can include more commands in the same line, by putting a colon (:) between them. A colon is treated as a command separator if it isn’t inside a pair of double quotes ("). For example:
  a = 1 : b = 2
  are the same two assignment commands.

Remarks are made by single quotes ('). Anything after a single quote (which isn’t inside a pair of double quotes ["]) up to the end of the line is a remark. Remarks don’t affect program execution in any way. For example:
  a = 1 ' gives a value to a variable
  is a command with an explaining text.

Long commands may be splitted into several lines, by adding an underscore (_) to their end, not inside a pair of double quotes ("). For example:
  ADD Lots, OneValue, NextValue, EvaluationOfAFunction(This, _
  That), EvaluationOfAnotherFunction(WithValue, WithAnotherValue), _
  FinalOne, NowReallyFinalOne
  is treated as a single command.

Lines can be indented with spaces and/or tabs to make levels of inclusion visible or for any purpose. Indentation does not affect execution. Spaces and tabs are disregarded between keywords, values and operators, too. Each line element must be separated from other elements with at least one space, but additional spaces don’t matter; for example:
  a = 5
  are the same commands.
  Spaces are disallowed inside keywords, names and numbers. Spaces inside a pair of double quotes (") are kept as they are during later handling of the text constant.

3.3. Keywords By Category

In this chapter, all currently defined LMPL keywords are listed. Functions are denoted by a preceding equal sign (=).

3.3.1. Handling Data Definition

Defining names often doesn’t require commands. Creating a part, a movcon, a model, a Dashboard, a tool or an object by using menu commands in building mode creates a default name (see section for it, too. Also, creating variables is done automatically, by referring to the variable. Defining group names is done by adding the first element to the group. Definition is required only in some limited cases.

GLOBAL variable[, variable […]]

Defines global variables. A global variable has the same value in all sections.

= TYPE(name)

Returns the type of a name. Gives back one of these values: "PART", "MOVCON", "MODEL", "MOVEMENT", "VARIABLE", "GROUP", "DASHBOARD", "TOOL", "OBJECT" or "UNDEFINED".


Deletes a name. This command deletes the name only, not the thing it is referring to. If there are other names of the object (e.g. it is a model and we issue the commands OtherName = Model1 : DELNAME Model1), the object can still be reached via its other names. If the name deleted was the only name for the object, it can be reached later via its numeric identifier (see section 3.2.1.) only. Assignment

variable = value

The assigment command is used to give a value to a variable. There is no type checking. The following is valid:
  MyVar = 1 + 1
  MyVar = "Bob"
  It is allowed to assign a value to a variable which previously contained a value of a different type.

INC variable [BY value]
  DEC variable [BY value]

Increases or decreases a variable by a given value; if value omitted, by 1. Renaming

RENAME oldname AS newname

Renames a name to another name. The oldname may be any name defined. Newname must differ from all currently existing names. After renaming, oldname becomes unavailable.

3.3.2. Code Execution Branching

Long syntax:

{IF|WHEN} condition {THEN|,}



Short syntax:

{IF|WHEN} condition {THEN|,} commands [ELSE] commands

With the IF/WHEN command, execution may be separated into branches. Branching is based upon a condition, what can be any expression giving a value. If this value is true, commands following THEN or the command are executed; if the value is false, commands following ELSE (if any) are executed. After that, execution is continuing after END IF/END WHEN (in the case of long syntax), or with the next line (in the case of short syntax), respectively.
  There is no functional difference between IF and WHEN. There are two words to choose from because the word WHEN may be easier to remember for durings. Looping

FOR variable = beginvalue TO endvalue [STEP stepvalue]


NEXT [variable]

Creates a loop with a predefined number of executions. When executing FOR, variable as assigned with beginvalue, and execution goes on until NEXT is reached. When reaching NEXT (if omitted here, variable refers to the topmost variable in the looping stack), variable becomes equal to variable + stepvalue, and if this is less than (in the case of a negative stepvalue, greater than) endvalue, execution goes back to the command following FOR.
  EXIT FOR terminates the loop and continues execution after NEXT.

DO [{UNTIL|WHILE} condition]


LOOP [{UNTIL|WHILE} condition]

Creates a loop with a predefined condition of execution. Either DO or LOOP may contain an {UNTIL|WHILE} condition part, or none of them; in no case can both lines contain such part. Condition can be any expression giving a value. If UNTIL is used, the loop is repeated until the value is true; if WHILE is used, the loop is repeated while the value is true. Condition is examined each time when the appropriate point of code (either the beginning or the end) is reached. If no condition specified, the loop can be terminated only by an EXIT DO command or a Stop command. (If the loop is in a during, stopping the during terminates any loops, too.)
  EXIT DO terminates the loop and continues execution after LOOP. Exiting


Quits the current section immediately. In INIT, can not be used. In DURING and GENERAL, quits execution of the section but does not change movement; movement remains as it is and the section is executed next time again. In PROC and FUNC, quits execution of the section.


Stops all movement, all execution and quits to the system. Running in the full version returns control to building mode. Running in the player version returns to the operating system.

3.3.3. Movement Control Controlling Movcons

= ME

In durings only: returns the identifier of the movement where the during is belonging to.


In durings only: returns the identifier of the movcon where the during is belonging to.

Later in this section, movement may be omitted in some syntaxes; if so, it defaults to ME. Also, movcon may be omitted in some syntaxes; if so, it defaults to MYCON. If both may be applied and both are omitted, it defaults to ME.


Available in any section, returns the ticks elapsed since beginning of execution of the General Process.

= TICKS[({movement|movcon})]

Returns the ticks elapsed since beginning of starting a movement.

= TICK(n[, {movement|movcon}])

Returns true if TICKS(movement) MOD n = 0; that is, in each Nth tick it returns true.

= SLI[({movement|movcon})]

Returns true if the movcon is sliding.

= ROT[({movement|movcon})]

Returns true if the movcon is rotating.

= DIST[({movement|movcon})]

Returns the distance of sliding, measured from the default state.

= ANGLE[({movement|movcon})]

Returns the angle of rotation, measured from the default state.

FIX [{movement|movcon}]

Registers the current state of the movcon as default state in the regards of DIST and ANGLE.

= POSX(part)
  = POSY(part)
  = POSZ(part)

Return the position of a part in the workspace, in absolute coordinates.

= POSX(part TO basepart)
  = POSY(part TO basepart)
  = POSZ(part TO basepart)

Return the position of a part in the workspace, compared to basepart.

= DIST(part1, part2)
  = DISTX(part1, part2)
  = DISTY(part1, part2)
  = DISTZ(part1, part2)

Return the distance, either as the crow flies or projected to each coordinate axis, between two parts.

  IDLE = value
  IDLEPAUSE = value

Return or change the values of the Idle or the Idlepause flag. Values allowed for Idle: "MOVING", "PAUSED", "BOTH", "NEITHER". Values allowed for Idlepause: "MOVING", "PAUSED". When setting the values, they can be shortened by one or more letters from their beginning.

START [{movement|movcon}]
  STOP [{movement|movcon}]
  PAUSE [{movement|movcon}]
  RESUME [{movement|movcon}]

Starts, stops, pauses or resumes a movement.

= STATE[({movement|movcon})]

Returns the state of the movement or movcon. Possible values are: "MOVING", "PAUSED", "IDLE".

= SLIDSPEED[({movement|movcon})]

Returns the speed of sliding.

= ROTSPEED[({movement|movcon})]

Returns the speed of rotation.

CHANGEMOV [{movement|movcon}] [STATE state] [SLIDSPEED slidspeed] [ROTSPEED rotspeed] [DIST dist] [ANGLE angle]

Changes one or more properties of the movement or movcon. Changing distance or angle makes the movcon to move to that state invisibly. Workspace


Clears the workspace (see section

LOADMODEL model FROM file [TO x, y, z] [ROT x, y, z]

Loads a model from a file and places it into a given position (if position omitted, leaves it in default position), optionally rotating it.

MOVEMODEL model [TO x, y, z]
  ROTMODEL model [BY x, y, z]

Moves a loaded model to a given position; rotate a model according to each axis.


Saves the current state of the workspace to a file.


Loads the state of the workspace from a file.


Reverts the state of the workspace.

ADDMODEL model FROM {file|name} [TO x, y, z] [ROT x, y, z]

Adds a model either from a file or by copying another model.


Removes a model from the workspace. Dashboards


Removes all Dashboards.

LOADDASH dashboard [TO x, y]

Loads a Dashboard from a file, optionally positioning it.

NEWDASH dashboard [TO x, y]

Creates a new Dashboard, optionally positioning it.

REMOVEDASH dashboard

Removes a Dashboard.

SAVEDASH dashboard TO file

Saves a Dashboard to a file.

LOADDASH dashboard FROM file [TO x, y]

Loads a Dashboard from a file, optionally positioning it.

NEWTOOL tool ON dashboard TYPE type [REF reference] [SETTING values]

Creates a tool on a Dashboard. Type can be one of the following: "PUSHBUTTON", "SWITCH", "SLIDE", "POTMETER", "DIGIT", "GRAPH", "HOUR", "DRAW", "PEEKER".
  Reference is the name of a section to be assigned with the tool; used only for controlling tools. This section is executed each time the tool is used by the user. The section may receive a value as a parameter:
  PUSHBUTTON – no parameter;
  SWITCH – "TRUE" or "FALSE", according to the state of switch;
  SLIDE, POTMETER – a number referring to the state of the tool.
  Setting specifies initial settings for the tool:
  SWITCH – "TRUE" if the switch is initially switched on, "FALSE" if off;
  SLIDE, POTMETER – three parameters. Value1 specifies the lowest value given back by the tool; value2 specifies the largest one; value3 specifies the initial setting according to value1 and value2. (For example, SETTING 0, 100, 50 in creating a Slider specifies that the leftmost position of the slide has to mean 0, the rightmost one has to mean 100, and initially the slider is at the middle point.)
  DIGIT – several parameters, all optional. FONT specifies the font to be used on the tool; omitted parameters revert to default settings. MASK specifies an output mask to be applied on values. Value1 is the initial value to be displayed.
  GRAPH, HOUR – see SLIDE, POTMETER. Additionally (optional): value4 specifies the color to be used.
  PEEKER – value1 specifies a camera to be assigned with the peeker.


Removes a tool. Changing Tools


Turns a switch on, off or over (to the opposite state). If NOOP is specified, the change is only visual. If NOOP is omitted, the assigned section is called as if the user would turn the switch.

SLIDER tool value [NOOP]
  POTMETER tool value [NOOP]

Slides a Slider or rotates a Potmeter to a value.

LIMITS tool lower upper value

Changes the limits of a Slider or a Potmeter and sets the value to a setting. Does not invoke the assigned section.

DIGIT tool value

Outputs a value on a Digit.

MODIFYTOOL tool [FONT fontname options] [COLOR color] [MASK mask] [GROUND ground]

Modifies settings for a tool. For Digits only: fontname is the name of the font to be used; options may be "BOLD", "ITALIC", "UNDERLINE", "STRIKETHROUGH", or more of these; mask is a string to be used as a display mask. For all tools: color is the main drawing color (in the case of a Draw, the current drawing color); ground is the background color.
  Display masks for a Digit tool contain characters # for digits and other characters being displayed literally.

DRAW tool commands

Executes drawing commands on a Draw tool. Drawing commands are:
  CLEAR – clears the drawing area;
  SCALE x1, y1, x2, y2 – rescales the drawing area, specifying a scale for further drawing commands;
  PUT name – displays an object specified by name. This may be a part, a model or a movcon; in this latter case, movcon is displayed by its forming parts in the current state;
  POINT x, y – draws a dot;
  LINE x1, y1, x2, y2 – draws a line;
  BOX x1, y1, x2, y2 – draws a rectangle;
  CIRCLE x1, y1, r – draws a circle;
  COLOR color – changes the drawing color;
  GROUND – changes background color, without clearing the drawing space.

PEEKER tool camera

Assigns a camera to the peeker, cancelling the previous assignment. Building And Destroying

BUILD partname MODEL model TYPE type COLOR color {TO x, y, z ROT x, y, z [NOCONNECT] | CONNECT prevpart way}

Builds a part. Partname is a name for the part, or an empty string ("") if no name is needed for the part; in this case, the part receives only a numeric identifier. Model is the model to treat the part beloning to. Type is a number identifying the part type (e.g. 3001). To position the part, either we specify TO and ROT, and optionally specify NOCONNECT to prevent LCD system from automatically connect the part to any neighbouring parts, or we specify CONNECT. Here, prevpart is the identifier for a previously existing part, and way is the way how to connecting it. This depends on the type of connection.

DESTROY partname

Destroys a part or a group. See section

RESTORE partname

Restores a previously destroyed part.

DISCONNECT {movcon|part1 part2}

Disconnects a connection.

CONNECT part1 part2 way [name]

Connects two parts, optionally giving the connection a name, if it is a movcon. Grouping

ADD groupname elementlist

Adds elements to a group, creating the group if not yet created. Elementlist is a comma-delimited list of values. Elements may be names (referring to anything able to be named) or constants.

DROP groupname elementlist

Removes elements from a group. Elementlist may contain selection references. Removing the last element from a group removes the group itself.

= groupname(selection)

Selects one or more elements of a group. Selection is a parameter specifying the way of selection:
  ALL – selects all elements;
  ANY – selects any element, best suiting for the context;
  ALL(categories), ANY(categories) – select all elements or any element according to one or more categories. A category may be any value what the TYPE function can return;
  FIRST – returns the first element according to the internal storage order, setting pointer to this element;
  LAST – returns the last element according to the internal storage order, setting pointer to this element;
  NEXT – returns the next element after the pointer; if it’s pointing to LAST, returns empty string ("");
  PREV – returns the previous element after the pointer; if it’s pointing to FIRST, returns empty string ("");
  PTR – returns the state of the pointer;
  COUNT – returns the number of elements;
  COUNT(categories) – returns the number of elements according to one or more categories (see above);
  number – returns an element by its number according internal storage order, not affecting the pointer.

… LIST list …

In section headers, denotes a parameter to be a list. For example:
  PROC MyProc (SingleValue1, LIST MyPara, SingleValue2)
  Such parameters can be supplied either with a single parameter:
  MyProc 1, 2, 3
  or with a list enclosed in parentheses:
  MyProc 1, (10, 20, 30, 40, 50), 2
  In this latter case, elements of the list are stored one by one in the name MyPara.

STEP list

Available in a section containing a LIST parameter, drops current element of the list and assigns next element to the name. If no more elements there, gives "OVER".


Available in a section containing a LIST parameter, sets the internal pointer back to the first element.

= COUNT(list)

Available in a section containing a LIST parameter, gives the number of elements in the list. Rendering


Selects displaying modes for further displaying. Defined modes are:
  "PLAIN" – the plainest mode possible;
  "NORMAL" – normal mode;
  "BEST" – the best mode possible;
  "LEGO", "NOLEGO" – turns the LEGO logo on studs on or off;
  "STUDS", "NOSTUDS", "LINESTUDS" – turns drawing of studs on, off or into straight lines;
  "WIRE", "NOWIRE" – turns wireframe mode on or off;
  "TRANS", "NOTRANS" – turns transparency on or off;
  "BACK", "NOBACK" – turns background on or off;
  "LIGHT", "NOLIGHT" – turns additional light sources on or off (affects raytracing modes only);
  "SHADOW", "NOSHADOW" – turns shadows on or off (affects raytracing modes only);
  "PERSP", "NOPERSP" – turns perspective on or off (affect raytracing modes only);
  "GRAPHICS", "NOGRAPHICS" – turns non-LDraw parts such as graphic images and text on or off;
  "LAMP", "AMBLAMP", "NOLAMP" – "LAMP" treats lighting LDraw parts as light sources; "AMBLAMP" treats them as ambient lights; "NOLAMP" treats them as colored ones simply.
  In a given Lego CAD software, the switches having effect may be a subset of these, according to capabilities of the software. For example, if the system doesn’t know raytracing, all switches concerning it are ineffective.

RENDER [camera] TO [NEXT] file WITH system [{NOW [WAIT]|AFTER}] [modes]

Creates a rendering of the current state by using an external renderer. Camera specifies a camera to be used for rendering; if omitted, the current camera is used. File is the name of a file to export the raytracing information; if preceded with NEXT, the file name is treated as a prefix and an incremental number is added to it. (For example, TO "model.pov" creates a file called model.pov, but TO NEXT "model.pov" creates several files called model1.pov, model2.pov etc.). System denotes the rendering software. Values defined:
  "POV" – exports to POV-Ray format;
  "3DS" – exports to 3D Studio format;
  "HTML" – exports to HTML format;
  "WAV" – exports to Wavefront format.
  In a given Lego CAD software, the switches having effect may be a subset of these, according to capabilities of the software. For example, if the system doesn’t know the 3D Studio format, the switch concerning it is ineffective.
  If NOW is specified, the system creates the file and immediately starts the renderer with the file given it; if WAIT is added after NOW, system has to wait until the renderer is ready with rendering (if this cannot be detected, the switch is ineffective). If NOW is omitted, only the file is created and execution goes on. If AFTER is specified, all files created during execution will be rendered after the whole animation has finished. If neither NOW nor AFTER is specified, it is up to the user to render the files.
  Modes are as the same settings as for the DISPLAY command. Settings for DISPLAY concern to the actual display; settings for RENDER concern to exported files.

SNAPSHOT [camera] TO [NEXT] file

Takes a snapshot of a camera to a file.

CAMERA [camera] [TO x, y, z] [ROT x, y, z] [POINT {x, y, z | part [{TURN|GO}]}] [ZOOM zoom]

Creates or modifies a camera, without changing the currently used camera. Camera may be omitted when changing settings for the current camera. POINT specifies a coordinate or a part the camera is pointing to. TURN makes the camera to follow that part on its movement, while the camera itself stays where it is, only rotates. GO makes the camera to follow that part on its movement, making the camera moving but not rotating. Zoom is a value controlling zooming: 1 is normal, greater than 1 zooms, less than 1 unzooms. (For example, 10 makes things ten times greater, 0.1 makes them ten times smaller.)
  Cameras are invisible for each other.


Switches over to the specified camera. There is always a camera created by the system in default, called MainCamera.


Removes a camera. If it is the currently used camera, the system switches back to MainCamera what cannot be removed.

LIGHT light [{AMBIENT|SPOT width}] [{SHADOW|NOSHADOW}] [TO x, y, z] [ROT x, y, z] [POINT {x, y, z | {part|camera} [{TURN|GO}]}] [COLOR color] [{ON|OFF}]

Creates or modifies a light source. SPOT denotes a spotlight what is pointing to a direction with a jet of light of a given width (1 is default width, greater than 1 is wider, smaller than 1 is narrower). AMBIENT denotes a spherical light. SHADOW makes the light to cast shadows, NOSHADOW turns them off. Rotation has no effect on ambient lights. Pointing has no effect on ambient lights if no following specified; if following is specified for an ambient light, it makes the shadows cast by it changing. Light sources can follow a camera also, to make light for the camera always. Color specifies the color of the light. OFF turns the light off without modifying its other properties (it continues following the part specified), ON turns it on again.
  Light sources themselves are invisible. They are being taken care of in certain rendering modes only. There is a default light called MainLight what cannot be deleted but can be turned off.


Removes a light source.


Specifies the background used for parts of the viewport not filled by LDraw parts or objects. Color specifies a solid to be used. File is an image file to take a tiled background to be taken from. OFF turns off the background, reverting to default setting.
  The background is taken care of in certain rendering modes only. Other Objects

GRAPHIC FROM file TO x, y, z ROT x, y, z [FOLLOW part {TURN|GO}] [TRANS color] [FACING]

Creates an in-workspace graphic (see section 2.13.) by loading it from an image file. It may follow a part either by turning after it or going along with it (e.g. it can be an arrow pointing to something important). Color specifies a transparent color. FACING makes the cameras to view the face of the graphic always, disregarding its rotation compared to the camera. However, it can still rotate around the axis connecting it with the camera.

GRAPHIC FROM file TO x, y [TRANS color]

Creates an out-workspace graphic.

TEXT text [FONT fontname] [COLOR color] [ITALIC] [BOLD] [UNDERLINE] [STRIKETHROUGH] TO x, y, z ROT x, y, z [FOLLOW part {TURN|GO}] [FACING]

Creates an in-workspace text title.


Creates an out-workspace text title.

4. Suggestions For Developing In LMPL

When LMPL is realized, developers can create full-fledged applications using Lego-like stages and actors, limited only by computing power. Here are some ideas what can we make with LMPL.

Lego Demos. These are usually animations playing with less or none of user interaction. Such demos can feature worlds built in virtual Lego with moving elements, for example, a Legoland town or other world built in a Lego theme. Or we can create animations showing how to build an official Lego set or an unofficial model.

Interactive Demos. Virtual Lego theme parks having several controls to interact with, becoming a transition between a demo and a fully controlled playing area. For example, the automatically working Legoland town can be cheered up with some user controllable models.

Playing Areas. Virtual Lego theme parks with full user control. For example, in a Legoland town, the player receives a town with streets, cars, houses and residents, and s/he can change everything: start or stop cars, design their movement, destroy or rearrange houses and so on.

Games. Any game what is known in 3D created realizations can be created in a Lego-like one. Examples in keywords only: shoot-em ups (from the ancient invader games to first person shooters, we mean first minifig shooters), arcade games (platform games, combat sports with Technic warriors, pacmans), simulators (cars, aircrafts, helicopters), board and strategy games (chess, checkers, war games), ball games (flippers, breakouts, tennis, soccer), adventure games.

Application software. It doesn’t have much sense to create a word processor or a net surfer application made up from Lego, even if there is sufficient computing power. However, we can create smaller utilities such as a calculator, a clock or other things.

Machines. However sometimes oversized, any mechanical machinery can be created in Lego in a realistic way; in virtual Lego with LMPL, it can be often as easy as in real. For example: vehicles, robots, piston engines etc. Who can build a working LDraw typewriter or an alarm clock?