Programming in Numipulator
Programming in Numipulator

The programming language of Numipulator really is very simple: you need to select the required functions/operations from drop-down lists and enter numbers or lists of numbers into boxes, together with reference names and maybe a few other reserved words that represent numbers or lists of numbers. The difficulty of programming a game in Numipulator will, of course, depend on the complexity of the game. Below is a fully-explained program for a simple game. Following that is a simple program for controlling an object in the Animation Zone with its keypad; this program can be used as a basis for any program involving movement of an object around the screen, and is set up to be easily modified for object size, screen size and number of cells moved per cycle. Lastly, the creation of complex graphical outputs in the Animation Zone is described, as is the simplicity of specifying irregular shapes using a table of numbers where the shape can be 'seen'.

Programming a simple game

The game included in Numipulator called Small red ball is designed to be a simple game to program and to understand. You can see and play the game by tapping here. It is a game to test your reactions.

The game is played on a 10x10 grid in the Graphics Formatter (this size is default). The idea is that each cell displays a shape (a small, medium or large circle (or ball), a small or medium square, or an arrow pointing left, right, up or down). Each one of these is coloured either red, green, blue, magenta, cyan or yellow, always on a black, borderless background. There may be several, or even none, of a particular shape/colour combination, but there is only one small red ball, as shown in the first image below. The player has a short time in which to spot the small red ball, and then to tap on it. At the end of the time allowed, a new screen is displayed, again with one small red ball. If the player has tapped on the correct cell, a green tick is displayed where the small red ball was, as shown in the second image below. The player's score is increased by 1 (shown in the Feedback). In contrast, if the player has tapped on the wrong cell, a red cross is displayed on the tapped cell in the next screen, together with a grey star showing where the small red ball was in the last screen. This situation is shown in the third image below, after the player has erroneously tapped on the cell below the target red ball. If the player fails to tap on any cell in the time allowed, only the grey star is shown on the next screen. This continues until the player has had 50 opportunities to score.

To program this, you need to know the format codes both for shapes and for colours. There are many options for shapes, but the shapes in the game were chosen to match the first nine shapes codes (1-9). The colours for the game were chosen because they have sequential colour codes (3-8). The format code for these shapes take the form NFGBG, where N is a shape number, FG is the foreground colour, and BG is the background colour (these are both two digits, so that a colour code of 3 must be represented as 03). The relevant values of N are:
1: small circle
2: medium circle
3: large circle
4: small square
5: medium square
6: up-arrow
7: right-arrow
8: down-arrow
9: left-arrow

The relevant foreground colours are:
3: Red
4: Green
5: Blue
6: Magenta
7: Cyan
8: Yellow

Now, a black background is specified by 00, so the format code 10300 is the code for a small ball (1), coloured red (03) on a black background (00), 10400 is the code for a small green ball on a black background, through to 90800, which is the code for a yellow left-arrow on a black background. To have no borders in the cells, negative equivalents of these must be used, e.g. -10400 and -90800.

Generating 100 shapes

To generate a screen with 100 cells as described, without, for now, the small red ball, you can use the List Generation function called p1 random ints p2->p3 to begin with. The input list consists of sets of three parameters: the first is the number of random numbers to generate, the second and third are the minimum and maximum integers from which the random numbers are to be taken. The results for each group of three are listed sequentially in the output.

Now, although the intention is to end up with codes such as -10400, -10500, -10600 and -70500, it is useful to mentally divide each of the format codes by -100, as then the numbers form sequences: 104, 105 ... 108, 203, 204, ... 209,...., 903, 904 ....908. Box G2 shows how you can generate 100 such numbers, where the input list is:
11 104 108
11 203 208
11 303 308
11 803 808
12 903 908

Points to note are that 103 is excluded, as this forms the basis of the small red ball (and the intention is to have exactly one of these), and that the request is for 11 of each of the first 8 shapes, but 12 for the last one, as this gives a total of 100 numbers.

Now the output of G2 has the base numbers of 11 small circles of varying colour, followed by 11 medium circles, and so on. One possible output for G2 is:
107 108 107 107 104 105 104 106 108 108 106 204 206 204 205 206 203 206 206 206 203 204 308 303 304 305 303 306 307 308 303 308 304 408 408 405 403 404 406 405 404 403 404 408 507 503 508 506 507 503 506 504 507 508 504 608 603 608 605 604 605 608 608 606 604 607 707 707 704 703 703 705 705 706 705 707 704 803 803 807 807 808 804 808 804 806 807 805 903 907 905 906 906 907 903 905 908 903 904 908

These need to be shuffled up to make the final display more confusing, so the output from G2 is fed in as the input to H1, with the Permutation function selected.

Finally, the numbers need to be multiplied by -100 to yield 100 valid format codes for shapes on a borderless black background, so H1 is defined as the first input of V1 and -100 as its second.

You can very easily test your program development by going to the Graphics Formatter and defining the main input parameters to be la=V1, ncols=10 and Cell formats to be V1. The same value for la and Cell formats can be used as these particular format codes ignore the values in la, so you might as well use the same values. Press the = button, and you should see 100 colourful shapes (but no small red ball, at this stage). Pressing it again should give you different shapes. You have produced a significant part of the overall program with just three numipulation boxes.

Determining the position of the small red ball in the new display

The positioning of the small red ball should be random, but with certain constraints: it cannot be placed on cells that will show feedback (tick, cross or star) from the previous display and user interaction, i.e. the previous position of the small red ball and the cell that the user tapped.

When the user taps on a Graphics Formatter cell, two fields are given new values: Graphin1 is given the row value, and Graphin2 is given the column value. Also, the internal value click is given the value 1 (the value is 0 if no tap is made). Probably the best way to deal with positions in this simple game is to give every cell of the Graphics Display an index number, from 1 to 100. You can use a Number Operation box, such as A2, to convert the row and column number to an index, using the Index: [a,b] 10 cols operation, which is designed to take the row and column number in a 10-column table and to output the index. It is, however, important to remember that if no tap is made, the values of Graphin1 and Graphin2 remain unchanged, so the output of A2 may not be the index of the tap just made, but of an earlier tap. To distinguish between a real and a false index, you can use an If-Then-Else (Simple) box, such as O1, to return either a true index or the value 0, by checking whether the value of click is 1 or not. So, the value of O1 is either the index of the cell just clicked, or 0, and the small red ball must not be placed at index O1.

Knowing the position of the small red ball in the previous display (if any) means that this must be remembered in a Number Memory box. Assume that you will use Y1 for this, so the value Y1 is another index in which the small red ball must not be placed.

The available indices for placing the small red ball are therefore 1-100, except for O1 and Y1. This list may be determined in box K1, which takes as inputs the integer list 1-100, as generated in List Generation box G1, and the list containing O1 and Y1, and outputs those values in 1-100 that do not appear in list O1 Y1. You can then take, randomly, any one of the output list of K1 to be the index for the small red ball, by using the Random item function in box C1. Note: any text between curly brackets {like this} is treated as a comment.

You can now program the Memory Number box, Y1, that is being used to remember the position of the small red ball. You know that the next value will be C1 (the position of the ball just determined). Note that this box must include an initial value (init) to be used for the first cycle since in the first cycle there won't have been a previous position of the small red ball, but you still need to specify a value otherwise the program would fail. Enter -1 for this initial value; the reason for this is discussed later.

Adding the small red ball and hit/miss indicators.

Your program has now determined the previous position of the small red ball (Y1), the index tapped by the player (O1) and the position of the new small red ball (C1). You must next ensure that the new small red ball and the feedback symbols are added in to the next display.

You can use the List & List Operation called Change values for taking an input list and making changes to this for the output list. It takes any number of sets of parameters, each of which is a pair of the form I V, where I is the index and V is the new value to be inserted at this index. Now, although you must always add in the new small red ball, the other feedback letters may or may not be needed: there is no need for a grey star in the first cycle or if the player has selected the correct position, and there is no hit/miss feedback in the first cycle or if the player has not tapped on a cell. The If-Then-Else (Simple) boxes O2, with its subsidiary O3, outputs parameters O1 -750400 (green tick) if the tap was a hit, O1 -760300 (red cross) if the tap was a miss, but an empty list in other cases (L0 is used to represent an empty list in Numipulator - a list of length 0). Boxes O4 and O5 output an empty list unless the tap was incorrect, in which case the parameters Y1 -770900 (grey star) are output.

O2 and O4 are fed in as part of the second input to K2, together with the parameters for the small red ball, C1 -10300, with V1 as the first input.

K2 can now be put into the Graphics Formatter fields for la and Cell formats (replacing the earlier V1 used for intermediate testing).

Before running your code, ensure that the Allow graphical input box in Graphics Control is checked (it is by default), and that you have defined init values for Graphin1 and Graphin2 (any valid values, e.g. 1 and 1, will do). These are needed, as Graphin1 and Graphin2 must have values defined even in the first cycle, otherwise an error would occur when trying to evaluate A1, which would cause the program to stop. The values entered here are not important, as long as they represent possible row and column numbers on a 10-column board; without an actual tap/click, the output value of O1 will be 0 regardless.

You can now test your code by pressing the Start button. At this stage, no repetitions have been specified, so the time allowed after a display is unlimited. Tapping on a cell should give you the correct feedback.

Repetitions and delay time

To make the game dynamic, you need to ensure that repetitions are specified, with a clear stopping point, and that the delay time is short enough to make it difficult, e.g. 2.5 seconds. First, put the value 2.5 in the Num1 numipulation box, and then enter Num1 as the delay time in the Control1 field of the Repetitions area; using Num1 means that a player could change this if it were a standalone game.

Next, you need to specify the Repeat until condition in the Repetitions area. Assume that you will use Y4 as the Number Memory box for number of cycles, so put in a terminating condition, say Y4 >= 50. Y4 is given an init specification of 0, while the next specification is A1, which simply takes Y1 and adds 1 to it each cycle (together these form a simple incrementor). Overall, this should ensure that the repetitions stop after 51 cycles (as the value of Y4 will be 0 for the first cycle, not 1).


The last functionality that needs to be handled is scoring. The score will be fed back to the player in the Feedback area of the Graphics Formatter.

The score is another value that needs a Memory Number box to remember it: Y3 has an init specification of 0, and a next specification of A3. A3 simply adds the input score (Y3) to O6, which is an If-Then-Else (Simple) box that has an output value of 1, if O1 = Y1 (signifying a hit), otherwise a value of 0; it is worth noting that this is the reason -1 is used as the init specification for Y1, rather than 0, to ensure that there is no false hit in the first cycle (which would happen if Y1 = 0). The new score A3 and the scorable cycles so far, Y4, are both values fed into the Feedback values. The other two values in this, -5 and -6, are there just to enable text rather than just two numbers as the feedback, as shown by number to text output mapping in the Feedback text and the resulting Feedback some way through a game.

The complete game involves 23 numipulation boxes only (including Control1, Graphin1 and Graphin2), together with a repetition constraint, settings and a number to text output mapping field.

Numipulator has a Flow button, which shows the dependencies within the program. As well as showing how the numipulation boxes feed into the Graphics Formatter, this also shows, underneath, the newY1, newY3 and newY4 values associated with the memory boxes. These do not directly feed into any other boxes, as they are treated as independent values used only by the processing engine to modify the mem inputs of Y1, Y3 and Y4 ready for the next cycle. Beneath these are the various control-related values.

The full program may also be viewed as text by pressing the Text link near the top of Numipulator. The full program for Small red ball is shown here, copied from the Text output. Please note that this text is useful only for inspecting the program more easily than by inspecting the numipulation box inputs within Numipulator, as much text may be hidden.

Moving an object in the Animation Zone

A common need in the Animation Zone is to move an object around using the keypad arrow keys. Below is a program for achieving this. You can see this in action by tapping here

So that this can be applied to many cases, the key numbers are specified in Common Numbers, which are referred to in other numipulation boxes, rather than being hard-coded into those boxes. The key numbers are the number of cells to be moved for any directional request (D1), the height of the object, i.e. number of rows in it (D2), the width of the object, i.e. number of columns in it (D3), and the board size (D4).

The only two values that need to be remembered from one cycle to the next in Memory Number boxes are the row of the top of the object (Y1) and the left column of the object (Y2). These have each been initiated as 1, so the object will initially be at the top-left corner of the Animation Zone.

Boxes C4 and C5 specify the change in rows and columns for all possible keypad requests (or none, if keypad = 0). These boxes make use of the Case: = function, in which the input list should be treated as several groups of three numbers forming a case statement (a sequence of if-then-elses). If the first of the three equals the second of the three, then the output is the third number; if not, the second group of three is checked, and so on; the spare number at the end is the default value to be used as the result if none of these checks succeed (0 in these cases). The changes shown are either the specified move (D1), or the negative equivalent (B1). The full input for C4 (the vertical change) is:
keypad 1 B1
keypad 2 B1
keypad 3 B1
keypad 7 D1
keypad 8 D1
keypad 9 D1
That is, the top three keys move it vertically in a negative direction (B1), the bottom three move it in a positive direction (D1), while any other key (or no key) leaves the vertical position unchanged. Note: in common with most systems, vertical moves are positive downwards, which may seem unintuitive.

A1 and A2 specify what the changed top row and left column of the object would be if the requested changes (C4 and C5) were made. A3 and A4 calculate what the bottom and right cells of the object would be if such a change were made (N.B. the bottom row is the changed top row, A1, plus the object height - 1 (B3); similar for columns).

For any keypad move request, it is crucial to check that the request is valid. For example, if the object were at the top of the board, a request to move upwards would be invalid. Box C3 checks whether the requested move is valid, using the Case: Comp function. This works in a similar way to the Case: = function, but the numbers are in groups of four, where the second number represents a comparison operator to be used in the check: 14 means <, 15 means <=, 16 means =, through to 19 means >. Input Mappings have been used (as shown in the diagram) to make these more readable. The full input list is:
A1 < 1 0
A3 > D4 0
A2 < 1 0
A4 > D4 0
which essentially means that it is invalid (result=0) if the object would be moved beyond the extremes of the board (< 1 or > D4, the board size), otherwise it is valid (result=1).

Having determined the validity of the request, C1 and C2 determine what the new values for the top row and left column are: the changed values (A1 and A2) if valid, or the input values (Y1 and Y2) if invalid. C1 and C3 are specified as the next values of Y1 and Y2, to be remembered for the next cycle.

With the new (or unchanged) position of the object determined, all that remains is to ensure that the Animation Zone displays the object in this position.

The Table Construction box, U1, uses the Change block values operation, which takes an input table (defined by inputs la and ncols) and sets of parameters in lc that will define changes made to blocks of values in the input list to create the output list. The value 0 for input d indicates that the output values are left as-is; any other value (e.g. -1) would result in their being multiplied by -1 - useful for converting bordered to borderless cells, and vice versa.

Each set of parameters in lc takes the following form: TLR (Row of top left cell of block), TLC (Column of top left cell of block), H (height of block in cells), W (width of block in cells), followed by HxW values that will become the new values for the defined block in the output. It is important to note that later sets of parameters in the overall list may overwrite changes made by earlier sets of parameters, although in this case only one set is specified.

In this case, la is specified as G1, a background of 0s (B2 is specifies as D4 squared), ncols=D4 (board size) and lc is specified by just one set of parameters, C1 C2 D2 D3 E1, where C1 and C2 are the top row and left column of the object, D2 and D3 are the height and width of the object, and E1 is a list of the format codes for the object (note the inclusion of some 0s in E1 so that those cells will merge into the background, resulting in an object that looks man-shaped rather than rectangular). U1 must be specified as the Cell formats list for the Animation Zone.

You must also specify a termination condition for repetitions, otherwise there will be only one cycle. There is no clear stopping point, and the intention in this case is just to test movement of the object in response to the keypad presses. So, set the condition to a check that should never succeed, such as 1 > 2. Press Start to test the behaviour.

Creating complex images in the Animation Zone

A game such as Alien Invasion involves many objects, some of which can move, some of which can be fired (missiles) or dropped (bombs), and most of which can be destroyed. Building up the image at each cycle must take care of all of these. Typically, such images (or the format codes for the image) will make use of operations in the Table Construction numipulation boxes. One such operation is Change block values, as discussed above.

Box U2 shows how this is used to create the table (list of numbers) for Alien Invasion. This time, several sets of parameters are used. The full text in lc is:

S7 {remaining aliens}
52 A4 3 5 O12 {launcher}
O7 {missile}
O6 {alien explosion maybe}
R2 {Bomb image}
O14 {Spare launchers}
O22 {Red ship}

This is a very simple-looking piece of code, but the result output will have 3600 (60x60) values in it. G1 in la inputs the 60x60 background values. In lc, the most straightforward line to understand is the second: 52 A4 3 5 O12. 52 is the top-left corner row of the missile launcher (it is always 52 as it moves horizontally only), A4 is the top-left corner column of the missile launcher, which will vary as it is moved using the keypad, the 3 and 5 are the height and width of the missile launcher block, and O12 will normally (unless it's just been hit) result in the launcher format code:
0 0 13 0 0
13 13 13 13 13
9 0 0 0 9

Similar to the parameters that were generated for Change values in the Small red ball program above, some of these lines may have a value that is an empty list. For example, missiles are dependent on the players actions, so there may not be one. The Red ship moves across randomly, so this may also be an empty list. The remaining aliens parameters may contain many values - the number reducing as aliens are shot down. If an alien has just been hit by a missile, it will still exist so, for simplicity, it will first be added with its usual values in parameters S7, but then these will be overwritten by O6, which will define format codes for an alien that has just been hit. At other times, O6 will be an empty list. R2 (Bomb image parameters) will generally be a list of five numbers, as a bomb occupies only one cell, but may be empty, e.g. if it has just destroyed an object.

Note that the format codes here are all positive (as for the missile launcher). The whole list is later multiplied by -1 to give the borderless cells required.

Seeing shape data for the Animation Zone

In the Fun Runner game, the runner is made up of a head, a body, two arms and two legs. The flexible input layout of number lists means that you can see the shape you're defining in the data. To explain, part of the data for arms is as follows, one of 8 positions for an arm, which can be seen in the table:

0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 7 7 7 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 7 7 7 7 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 7 7 7 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 7 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

The 0s represent the background, the 1s represent the track suit (these will be replaced by the code for the appropriate shade of grey, depending on whether the arm is near or far, and the 7s represent the hand. Designing shapes can be quite easy in this way.

Copyright TopAccolades Limited, 2023