In this exercise we will use the editor of MakeCode. You can find the editor on our website in the navigation at the top: Programming - Editor.
Depending on which mode is currently active, different code should be executed. Therefore we create an if-then-query and define a condition for each mode. Here is a short overview of the required modes. At the end of point 7 there is a summary and a detailed description of these modes,
In this mode both players can set their ships. The Calliope can't check that the ships are set according to the rules - but that's something you'll notice when you play the game, so let's focus on fair play.
The player who is in this mode can attack a field of the other player.
In this mode you can only wait for the attack of the other player.
The game is over, the player has won.
The game is over, the other player has won.
When the player has triggered the attack, the Calliope switches to this mode to transmit the coordinates of the attacked field to the other player.
When the player has received the attack, he switches to this mode to radio the result, i.e. whether a hit was scored or not, back to the other player.
The first one to finish his ships starts the attack. Since this attack can only take place when the other player has also set his ships, the player "waits" in this mode.
At startup, required variables are defined:
For the own ships and the own shots a multidimensional array is created. The multidimensional arrays each contain 5 arrays with 5 numbers, one for each LED (pixel) on the Calliope. The first dimension corresponds to the Y-value and the second to the X-value on the LED matrix. At the beginning all numbers are set to 0. In the course of the game these pixels are set to different values, each representing a certain state:
0 = no ship
1 = A shot of the opponent, which has landed in water
2 = A hit of the opponent on an own ship
9 = An own ship
0 = field not yet fired
1 = One own shot at the enemy, which has landed in the water
9 = A hit on the enemy ship
The LEDs on the Calliope Mini can be addressed via X and Y values. The first LED is x=0,y=0. The last LED is x=4,y=4. To set the "crosshairs" to start in the middle, the variables "crosshair_x " and "crosshair_y " are both set to 2.
Next we define a variable in which the current mode is stored. Depending on which mode is active, the MINI should execute different code. In the permanent loop, this is done with an extensive if-then query. To start, the ships must be set, so we set the variable to "set ".
Finally we define in the variable "max_schiffe" how many ships may be set.
Furthermore the following variables are needed, but not defined further (their value is 0):
team: This variable stores who attacks first.
ships_set: Stores how many ships were set.
hits: Stores how many hits the opponent has scored.
result: Saves the result of the opponent's attack.
attack_x: Saves the X-coordinate of the opponent's attack
attack_y: Stores the Y-coordinate of the opponent's attack
Since MakeCode does not yet support the passing of variables in functions, these variables must be created for caching.
If the number of set ships corresponds to the number set in "max_ships", the mode is changed to "team selection" and the crosshairs are reset to the center.
In the Set mode the set ships and the crosshairs should be displayed. For this purpose, the function "LED_Set" is called.
In Attack mode, the shots and the crosshairs should be displayed. For this purpose the function "LED_Angriff" is called.
In defense mode, the value "funk_ende = 0" is sent to inform the other MINI that the defense mode is active and thus a new "radio entertainment" can begin for the next attack.
The "Check for Attack" function is then used to check whether the X and Y values have already been received from the next attack and, if necessary, to change the mode to "Send_Defense".
With the function "LED_Defense" the own ships and the previous shots of the opponent are displayed.
A smiley is displayed in the won mode
The result is sent to the other MINI to let it know that it has won.
Afterwards a sad smiley is displayed.
The RGB LED is set to orange.
Afterwards, first the Y-value and then the X-value of the crosshairs is sent as an attack.
The RGB LED is set to blue.
The attacked pixel is switched in a for loop 20x. So 10 times on and 10 times off, with a pause of 50 ms each.
The two attack variables are set back to -1.
The result of the attack is sent in the variable "a_rueckgabe" to the other MINI.
If the "team" variable is already set to 1, Then the MINI goes into "defense" mode.
Otherwise the value "team = 1" is sent to the other MINI to set the variable to the appropriate value.
LED_Attack(), LED_Set() and LED_Defense()
The RGB LED is set to one color depending on the mode.
All LEDs are switched off
In the Attack and Set modes, the crosshairs are drawn, they glow continuously.
Depending on the mode, different pauses and the call of the function "doSwitch on" will cause different flashing. To do this, the array "switch on_array " is set to "ships " or "shots " and the variable "switch on_value " is set to the value at which the corresponding LEDs should be switched on.
With a nested for loop, each value from the array stored in "switch on_array " is compared with the value stored in "switch on_value ".
If both values are equal, the LED at the corresponding position is switched on.
If the X and Y values of the attack are no longer at the default value, i.e. greater than or equal to 0, then an attack was successfully transmitted.
If at the X- and Y-position of the attack in the array "ships " is a 0, then there is water. So the value in the ship array is set to 1 to represent a water hit.
The result is also set to 1.
otherwise is a 0 to represent a hit. The value in the ship array is set to 2 to represent a hit.
The hit counter "hit" is increased by one.
The result is set to 9.
If the number of hits is equal to the value set in "ships_max ", then all set ships are hit and sunk. The result is set to 99 and the mode is changed to "lost".
Otherwise the mode is changed to "send_defense".
If the mode is set to attack or set, input is accepted.
The Y-value of the crosshairs is increased by one.
If the Y-value is set to 5 and thus exceeds the maximum value, the value is reset to 0. The crosshair appears again at the other end of the matrix.
Like button A, but with the X-value.
Button A & B
In the Mode Set it is checked whether no ship is set at the crosshair position, i.e. the value is 0.
If this is the case, then the value is set to 9 at the corresponding position.
The number of ships is increased by one.
And for confirmation a tone of 500Hz is played for 1/16 beat.
Otherwise the middle C is played for one bar.
In Mode Attack it is checked if no shot has been fired at this point, so the value is still 0.
If this is the case, a tone of 500 Hz is played for 1/16 beat and the mode is changed to "send_attack.
Otherwise the middle C is played for one bar.
In Mode Defense the local variable "attack_y " is set to the received value when the variable "a_field_y " is received.
The same applies to the variable with the X-value.
In the mode "send_attack " it is checked on receipt of the variable "a-return " whether it contains the value 99.
If this is the case, the other MINI has lost and the mode is changed to "won".
Otherwise the received value is written to the attacked position in the shot array.
The RGB LED is set to violet.
If the received value is 9, this means a hit. A check mark is displayed.
Else an X is displayed.
after one second the mode is changed to defense. The attack is completed.
In mode "send_defense " and "team selection " the mode is changed to "attack " when the variable "funk_end " is received.
In the mode Set the local variable "team" is set to 1 when the variable "team " is received.
This mode is active as soon as the Calliope Mini is started.
In this mode the Calliope should be an active field that can be changed using the A and B keys. By pressing both keys you can set a skipping point on the corresponding field.
The corresponding pixels should flash where ship points have already been set.
Whenever a ship point is set the variable "ship_set" should be increased by one.
As soon as the number of set ships corresponds to the variable "ships_max" the mode should be changed to team selection.
Also in this mode an active field is displayed and changed with the A and B keys. By pressing both keys the corresponding field of the opponent is attacked. The mode is changed to "send_attack".
On the Calliope Mini the fields already attacked should flash. Hits on the enemy ships should glow longer and shots into the water should be short.
In this mode there are no interaction possibilities. Your own ships will glow permanently. Enemy hits are blinking long and the enemy ships that have landed in the water are blinking short.
So the enemy Calliope knows that attacks can be "received" and the Calliope Mini is currently "passive" the value "funk_end = 0" is sent.
As soon as the Calliope receives a radio signal with the name "a_feld" (the "a" stands for "attack") he checks the result of the attack and writes it into the variable "ergebniss" and at the corresponding position into the array "ships".
If a hit occurs, the variable "hit" is increased by one. If the variable "hit" corresponds to the variable "ships_max", the mode is changed to "lost". Otherwise the Calliope changes to the mode "send_defense".
A smiley is displayed and the game is over.
A sad smiley is displayed and the game is over. To inform the Calliope Mini of the end of the game the value "a_rueckgabe = 99" is sent.
The field to be attacked is sent by radio. The Calliope now waits for the opposing Calliope to send back the result of the attack.
If the result is "99" the mode is changed to "Won".
If the result is "9" a check mark is displayed for one second and the result is written into the array "shots" at the corresponding position.
The same applies to a result of "1", except that in this case an "X" is displayed for one second.
Afterwards the mode is set to "Defense".
The attacked point is indicated by a fast flashing of the corresponding LED.
The result of the attack is sent to the other Calliope until the other Calliope signals by sending "funk_ende" that it has received the result and is now in defense mode itself. The mode is now changed to "attack".
The Calliope, which first changes to this mode sends the signal "team = 1" until it recognizes with the reception of "funk_ende" that the opponent is now in the mode "defense". The mode is then set to "attack".
When receiving "team=1" from the other Calliope, the value "team" is set to "1". When the other Calliope switches to "team selection" mode, the mode is immediately changed to "defense".