#define SW_VERS "v1.10"
// TARGET
// LOLIN(WEMOS) D1 R2 & mini
// DEBUG Const
#define DEBUG false //set to true for debug output, false for no debug output
#define DEBUG_SERIAL \
if (DEBUG) Serial
// MSG Const
#define MSG true //set to true for msg output, false for no msg output
#define MSG_SERIAL \
if (MSG) Serial
#include <Adafruit_NeoPixel.h>
#include "BTN.h"
// Pin assignment
#define PIN_LED 2
#define PIN_LED_TURN_PLAY1 3
#define PIN_LED_TURN_PLAY2 4
#define PIN_BUTTONS_PLAY1 {23, 25, 27, 29, 31, 33, 35}
#define PIN_BUTTONS_PLAY2 {49, 47, 45, 43, 41, 39, 37}
#define PIN_SWITCH_P1 10
#define PIN_SWITCH_P2 11
#define PIN_BUTTON_POWER 7
#define PIN_LED_POWER 6
// HW Constant
#define NUM_ROWS 6
#define NUM_COLS 7
#define NUM_PLAYS 2
#define NUM_LEDS NUM_ROWS*NUM_COLS*NUM_PLAYS
#define BRIGHTNESS 255
#define BRIGHTNESS_TURN 100
// SW Constant
#define TIME_INACTIVE 300000
// HW Global variables
Adafruit_NeoPixel ledStrip(NUM_LEDS, PIN_LED, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel ledStripTurnPlay1(1, PIN_LED_TURN_PLAY1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel ledStripTurnPlay2(1, PIN_LED_TURN_PLAY2, NEO_GRB + NEO_KHZ800);
MyBtn btnPlay1[NUM_COLS];
MyBtn btnPlay2[NUM_COLS];
int pinButtonsPlay1[NUM_COLS] = PIN_BUTTONS_PLAY1;
int pinButtonsPlay2[NUM_COLS] = PIN_BUTTONS_PLAY2;
// SW Global variables
enum gameStateEnum {POWER_OFF, INIT_MM, INPUT_MM, PUT_PIECE_MM, UNLOAD_COL_MM, UNLOAD_MM, INIT_F4, START_F4, PLAY_MOVE_F4, PUT_PIECE_F4, CHECK_WIN_F4, WIN_F4, FINISH_F4, UNLOAD_F4, INIT_NB, START_NB, PLAY_MOVE_NB, ATTACK_NB, CHECK_WIN_NB, WIN_NB, FINISH_NB};
enum gameStateEnum gameState = POWER_OFF;
enum gameStateEnum gameStateOld = START_F4;
uint8_t gameSel = 0;
uint32_t timerActive = 0;
bool first = false;
bool readyPlay1 = false;
bool readyPlay2 = false;
const uint8_t NUM_COLOR_PALETTE = 5;
uint32_t colorPalette[NUM_COLOR_PALETTE] = {0xFFC4EB, 0xF0CE36, 0xAF0000, 0xFFFBBD, 0x007D57};
const uint32_t colorPlay1 = ledStrip.gamma32(colorPalette[1]);
const uint32_t colorPlay2 = ledStrip.gamma32(colorPalette[2]);
const uint32_t colorWater = ledStrip.gamma32(colorPalette[4]);
bool winnerPlay = false;
uint8_t turno = 1;
uint32_t color = 0;
struct line {
uint8_t rowStart;
uint8_t colStart;
int8_t deltaRow;
int8_t deltaCol;
uint8_t numPieces;
};
line winLineF4;
int row = 0;
int col = 0;
// Naval Battle
#define NUM_SHIPS 4
#define TOT_SHIP_SEGMENTS (4+3+2+2)
line shipsPlay1[NUM_SHIPS] = {
//portaerei
{0, 0, 0, 1, 4},
//incrociatore
{0, 0, 0, 1, 3},
//cacciatorpediniere
{0, 0, 0, 1, 2},
//sottomarino
{0, 0, 0, 1, 2}
};
line shipsPlay2[NUM_SHIPS] = {
//portaerei
{0, 0, 0, 1, 4},
//incrociatore
{0, 0, 0, 1, 3},
//cacciatorpediniere
{0, 0, 0, 1, 2},
//sottomarino
{0, 0, 0, 1, 2}
};
uint8_t shipsPlacedPlay1 = 0;
uint8_t shipsPlacedPlay2 = 0;
enum shotStateEnum {UNKNOWN, WATER_BLINK, WATER, HIT_BLINK, HIT, SUNK_BLINK, SUNK};
enum shotStateEnum shotsPlay1[NUM_ROWS][NUM_COLS] = {UNKNOWN};
enum shotStateEnum shotsPlay2[NUM_ROWS][NUM_COLS] = {UNKNOWN};
uint8_t scorePlay1 = 0;
uint8_t scorePlay2 = 0;
bool overlapPlay1 = false;
bool overlapPlay2 = false;
bool autoPilotPlay1 = false;
bool autoPilotPlay2 = false;
// Music Mode
uint8_t unloadThreshold[NUM_COLS] = {2, 2, 3, 4, 5, 6, 6};
// Variables for messages
uint8_t gameCode = 0; // 1 = F4, 2 = NB, 3 = MM
uint8_t outcomeAttack;
#include "F4.h"
#include "NB.h"
void setup() {
Serial.begin(9600);
for (int i=0; i<NUM_COLS; i++) {
pinMode(pinButtonsPlay1[i], INPUT_PULLUP);
btnPlay1[i].configPin(pinButtonsPlay1[i]);
pinMode(pinButtonsPlay2[i], INPUT_PULLUP);
btnPlay2[i].configPin(pinButtonsPlay2[i]);
}
pinMode(PIN_SWITCH_P1, INPUT_PULLUP);
pinMode(PIN_SWITCH_P2, INPUT_PULLUP);
pinMode(PIN_BUTTON_POWER, INPUT_PULLUP);
pinMode(PIN_LED_POWER, OUTPUT);
ledStrip.begin();
ledStripTurnPlay1.begin();
ledStripTurnPlay2.begin();
ledStrip.setBrightness(BRIGHTNESS);
ledStripTurnPlay1.setBrightness(BRIGHTNESS_TURN);
ledStripTurnPlay2.setBrightness(BRIGHTNESS_TURN);
}
void loop() {
if (gameState != POWER_OFF) {
// Leggo selettore gioco
if (readGameSelSwitch(&gameSel)) {
timerActive = millis();
switch (gameSel) {
case 0:
gameState = INIT_MM;
break;
case 1:
gameState = INIT_F4;
break;
case 2:
gameState = INIT_NB;
break;
default:
break;
}
}
// Leggo pulsanti
if (readButtons()) {
timerActive = millis();
}
if ((millis() - timerActive) > TIME_INACTIVE) {
switch (gameSel) {
case 0:
gameState = INIT_MM;
break;
case 1:
gameState = INIT_F4;
break;
case 2:
gameState = INIT_NB;
break;
default:
break;
}
}
if (!readPowerButton()) {
gameState = POWER_OFF;
}
}
// First evaluation for first time in new state
if (gameStateOld != gameState) {
first = true;
gameStateOld = gameState;
}
switch (gameState) {
case POWER_OFF:
if (first) {
first = false;
ledStrip.clear();
ledStrip.show();
ledStripTurnPlay1.clear();
ledStripTurnPlay2.clear();
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
digitalWrite(PIN_LED_POWER, LOW);
DEBUG_SERIAL.println("POWER_OFF");
}
readGameSelSwitch(&gameSel);
if (readPowerButton()) {
// Gioco acceso
digitalWrite(PIN_LED_POWER, HIGH);
switch (gameSel) {
case 0:
gameState = INIT_MM;
break;
case 1:
gameState = INIT_F4;
break;
case 2:
gameState = INIT_NB;
break;
default:
break;
}
timerActive = millis();
}
break;
case INIT_MM:
if (first) {
first = false;
animInitMM(true);
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
ledStrip.clear();
ledStrip.show();
gameCode = 3;
MSG_SERIAL.print("GM_");
MSG_SERIAL.println(gameCode);
DEBUG_SERIAL.println("INIT_MM");
}
animInitMM();
// Controllo pressione tasto giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasReleased()) {
btnPlay1[i].clearReleased();
ledStrip.clear();
ledStrip.show();
gameState = INPUT_MM;
}
}
// Controllo pressione tasto giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasReleased()) {
btnPlay2[i].clearReleased();
ledStrip.clear();
ledStrip.show();
gameState = INPUT_MM;
}
}
break;
case INPUT_MM:
if (first) {
first = false;
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
DEBUG_SERIAL.println("INPUT_MM");
}
// Controllo pressione tasto giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasReleased()) {
btnPlay1[i].clearReleased();
if (ledStrip.getPixelColor(getNumLed(0, i, 1)) == 0) {
col = i;
color = ledStrip.gamma32(colorPalette[random(NUM_COLOR_PALETTE)]);
turno = 1;
gameState = PUT_PIECE_MM;
}
}
}
// Controllo pressione tasto giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasReleased()) {
btnPlay2[i].clearReleased();
if (ledStrip.getPixelColor(getNumLed(0, i, 1)) == 0) {
col = i;
color = ledStrip.gamma32(colorPalette[random(NUM_COLOR_PALETTE)]);
turno = 2;
gameState = PUT_PIECE_MM;
}
}
}
// Scarico pezzi
if ((btnPlay1[0].wasLongPressed()) && (btnPlay1[NUM_COLS-1].wasLongPressed())) {
btnPlay1[0].clearLongPressed();
btnPlay1[NUM_COLS-1].clearLongPressed();
MSG_SERIAL.println("MM_UNLOAD");
gameState = UNLOAD_MM;
}
if ((btnPlay2[0].wasLongPressed()) && (btnPlay2[NUM_COLS-1].wasLongPressed())) {
btnPlay2[0].clearLongPressed();
btnPlay2[NUM_COLS-1].clearLongPressed();
MSG_SERIAL.println("MM_UNLOAD");
gameState = UNLOAD_MM;
}
break;
case PUT_PIECE_MM:
if (first) {
first = false;
DEBUG_SERIAL.println("PUT_PIECE_MM");
}
if (putPiece(col, color)) {
MSG_SERIAL.print("MM ");
MSG_SERIAL.print(turno);
MSG_SERIAL.print(" ");
MSG_SERIAL.println(getCodeLed(row, col));
if ((NUM_ROWS-row) >= unloadThreshold[col]) {
MSG_SERIAL.print("MM_UNLOAD_COL ");
MSG_SERIAL.println(col);
gameState = UNLOAD_COL_MM;
}
else {
gameState = INPUT_MM;
}
}
break;
case UNLOAD_COL_MM:
if (first) {
first = false;
unloadThreshold[col] = random(2, NUM_ROWS+1);
DEBUG_SERIAL.println("UNLOAD_COL_MM");
}
if (unloadColPieces(col)) {
gameState = INPUT_MM;
}
break;
case UNLOAD_MM:
if (first) {
first = false;
for (int i=0; i<NUM_COLS; i++) {
unloadThreshold[i] = random(2, NUM_ROWS+1);
}
DEBUG_SERIAL.println("UNLOAD_MM");
}
if (unloadPieces()) {
gameState = INPUT_MM;
}
break;
case INIT_F4:
if (first) {
first = false;
animInitF4(true);
ledStrip.clear();
ledStrip.show();
ledStripTurnPlay1.setPixelColor(0, colorPlay1);
ledStripTurnPlay2.setPixelColor(0, colorPlay2);
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
readyPlay1 = false;
readyPlay2 = false;
gameCode = 1;
MSG_SERIAL.print("GM_");
MSG_SERIAL.println(gameCode);
DEBUG_SERIAL.println("INIT_F4");
}
animInitF4();
// Controllo pressione tasto giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasReleased()) {
btnPlay1[i].clearReleased();
readyPlay1 = true;
ledStripTurnPlay1.setPixelColor(0, colorPlay2);
ledStripTurnPlay1.show();
}
}
// Controllo pressione tasto giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasReleased()) {
btnPlay2[i].clearReleased();
readyPlay2 = true;
ledStripTurnPlay2.setPixelColor(0, colorPlay1);
ledStripTurnPlay2.show();
}
}
if (readyPlay1 && readyPlay2) {
//animInitF4(true);
gameState = START_F4;
}
break;
case START_F4:
if (first) {
first = false;
ledStrip.clear();
ledStrip.show();
ledStripTurnPlay1.clear();
ledStripTurnPlay2.clear();
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
DEBUG_SERIAL.println("START_F4");
}
if (animStartF4()) {
gameState = PLAY_MOVE_F4;
}
break;
case PLAY_MOVE_F4:
if (first) {
first = false;
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
if (turno == 1) {
ledStripTurnPlay1.fill(colorPlay1);
ledStripTurnPlay2.fill(colorPlay1);
}
else {
ledStripTurnPlay1.fill(colorPlay2);
ledStripTurnPlay2.fill(colorPlay2);
}
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
DEBUG_SERIAL.println("PLAY_MOVE_F4");
}
if (turno == 1) {
// Verifico mossa del giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasReleased()) {
btnPlay1[i].clearReleased();
if (ledStrip.getPixelColor(getNumLed(0, i, 1)) == 0) {
col = i;
gameState = PUT_PIECE_F4;
}
}
}
}
else {
// Verifico mossa del giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasReleased()) {
btnPlay2[i].clearReleased();
if (ledStrip.getPixelColor(getNumLed(0, i, 2)) == 0) {
col = i;
gameState = PUT_PIECE_F4;
}
}
}
}
// Scarico pezzi
if ((btnPlay1[0].wasLongPressed()) && (btnPlay1[NUM_COLS-1].wasLongPressed())) {
btnPlay1[0].clearLongPressed();
btnPlay1[NUM_COLS-1].clearLongPressed();
MSG_SERIAL.println("F4_UNLOAD");
gameState = UNLOAD_F4;
}
if ((btnPlay2[0].wasLongPressed()) && (btnPlay2[NUM_COLS-1].wasLongPressed())) {
btnPlay2[0].clearLongPressed();
btnPlay2[NUM_COLS-1].clearLongPressed();
MSG_SERIAL.println("F4_UNLOAD");
gameState = UNLOAD_F4;
}
break;
case PUT_PIECE_F4:
if (first) {
first = false;
if (turno == 1) {
color = colorPlay1;
}
else {
color = colorPlay2;
}
DEBUG_SERIAL.println("PUT_PIECE_F4");
}
if (putPiece(col, color)) {
MSG_SERIAL.print("F4 ");
MSG_SERIAL.print(turno);
MSG_SERIAL.print(" ");
MSG_SERIAL.println(getCodeLed(row, col));
gameState = CHECK_WIN_F4;
}
break;
case CHECK_WIN_F4:
if (first) {
first = false;
winnerPlay = false;
DEBUG_SERIAL.println("CHECK_WIN_F4");
}
if (!checkWinF4(color, &winLineF4)) {
if (turno == 1) {
turno = 2;
}
else {
turno = 1;
}
gameState = PLAY_MOVE_F4;
}
else {
MSG_SERIAL.print("F4_WIN ");
MSG_SERIAL.println(turno);
gameState = WIN_F4;
}
break;
case WIN_F4:
if (first) {
first = false;
DEBUG_SERIAL.println("WIN_F4");
}
if (animWinF4()) {
gameState = FINISH_F4;
// Prossimo gioco inizia chi ha perso
if (turno == 1) {
turno = 2;
}
else {
turno = 1;
}
}
break;
case FINISH_F4:
if (first) {
first = false;
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
DEBUG_SERIAL.println("FINISH_F4");
}
// Controllo pressione tasto giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasPressed()) {
btnPlay1[i].clearPressed();
MSG_SERIAL.println("F4_UNLOAD");
gameState = UNLOAD_F4;
}
}
// Controllo pressione tasto giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasPressed()) {
btnPlay2[i].clearPressed();
MSG_SERIAL.println("F4_UNLOAD");
gameState = UNLOAD_F4;
}
}
break;
case UNLOAD_F4:
if (first) {
first = false;
DEBUG_SERIAL.println("UNLOAD_F4");
}
if (unloadPieces()) {
gameState = INIT_F4;
}
break;
case INIT_NB:
if (first) {
first = false;
ledStrip.clear();
ledStrip.show();
ledStripTurnPlay1.setPixelColor(0, colorPlay1);
ledStripTurnPlay2.setPixelColor(0, colorPlay2);
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
readyPlay1 = false;
readyPlay2 = false;
shipsPlacedPlay1 = 0;
shipsPlacedPlay2 = 0;
scorePlay1 = 0;
scorePlay2 = 0;
overlapPlay1 = false;
overlapPlay2 = false;
autoPilotPlay1 = false;
autoPilotPlay2 = false;
// Inizializzazione navi
for (int i=0; i<NUM_SHIPS; i++) {
switch (i) {
case 0:
shipsPlay1[i] = {0, 0, 0, 1, 4};
shipsPlay2[i] = {0, 0, 0, 1, 4};
break;
case 1:
shipsPlay1[i] = {0, 0, 0, 1, 3};
shipsPlay2[i] = {0, 0, 0, 1, 3};
break;
case 2:
shipsPlay1[i] = {0, 0, 0, 1, 2};
shipsPlay2[i] = {0, 0, 0, 1, 2};
break;
case 3:
shipsPlay1[i] = {0, 0, 0, 1, 2};
shipsPlay2[i] = {0, 0, 0, 1, 2};
break;
default:
break;
}
}
gameCode = 2;
MSG_SERIAL.print("GM_");
MSG_SERIAL.println(gameCode);
DEBUG_SERIAL.println("INIT_NB");
}
animInitNB();
// Controllo pressione tasto giocatore 1
if (!readyPlay1) {
if (!autoPilotPlay1) {
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasPressed()) {
btnPlay1[i].clearPressed();
switch(i) {
case 0: //Su
if ((shipsPlay1[shipsPlacedPlay1].rowStart) > 0) {
drawShip(&shipsPlay1[shipsPlacedPlay1], 0, 1);
shipsPlay1[shipsPlacedPlay1].rowStart--;
}
break;
case 1: //Giù
if (((shipsPlay1[shipsPlacedPlay1].rowStart)+(((shipsPlay1[shipsPlacedPlay1].numPieces)-1)*shipsPlay1[shipsPlacedPlay1].deltaRow)) < (NUM_ROWS-1)) {
drawShip(&shipsPlay1[shipsPlacedPlay1], 0, 1);
shipsPlay1[shipsPlacedPlay1].rowStart++;
}
break;
case 2: //Sinistra
if ((shipsPlay1[shipsPlacedPlay1].colStart) > 0) {
drawShip(&shipsPlay1[shipsPlacedPlay1], 0, 1);
shipsPlay1[shipsPlacedPlay1].colStart--;
}
break;
case 3: //Destra
if (((shipsPlay1[shipsPlacedPlay1].colStart)+(((shipsPlay1[shipsPlacedPlay1].numPieces)-1)*shipsPlay1[shipsPlacedPlay1].deltaCol)) < (NUM_COLS-1)) {
drawShip(&shipsPlay1[shipsPlacedPlay1], 0, 1);
shipsPlay1[shipsPlacedPlay1].colStart++;
}
break;
case 4:
autoPilotPlay1 = !autoPilotPlay1;
break;
case 5: //Ruota
drawShip(&shipsPlay1[shipsPlacedPlay1], 0, 1);
if (shipsPlay1[shipsPlacedPlay1].deltaRow > 0) {
shipsPlay1[shipsPlacedPlay1].deltaRow = 0;
shipsPlay1[shipsPlacedPlay1].deltaCol = 1;
if (((shipsPlay1[shipsPlacedPlay1].colStart)+(((shipsPlay1[shipsPlacedPlay1].numPieces)-1)*shipsPlay1[shipsPlacedPlay1].deltaCol)) > (NUM_COLS-1)) {
shipsPlay1[shipsPlacedPlay1].colStart = NUM_COLS - 1 - (((shipsPlay1[shipsPlacedPlay1].numPieces)-1)*shipsPlay1[shipsPlacedPlay1].deltaCol);
}
}
else {
shipsPlay1[shipsPlacedPlay1].deltaRow = 1;
shipsPlay1[shipsPlacedPlay1].deltaCol = 0;
if (((shipsPlay1[shipsPlacedPlay1].rowStart)+(((shipsPlay1[shipsPlacedPlay1].numPieces)-1)*shipsPlay1[shipsPlacedPlay1].deltaRow)) > (NUM_ROWS-1)) {
shipsPlay1[shipsPlacedPlay1].rowStart = NUM_ROWS - 1 - (((shipsPlay1[shipsPlacedPlay1].numPieces)-1)*shipsPlay1[shipsPlacedPlay1].deltaRow);
}
}
break;
case 6: //Piazza
// Controllo sovrapposizioni
overlapPlay1 = false;
for (int segment=0; segment<shipsPlay1[shipsPlacedPlay1].numPieces; segment++) {
if (checkShip(1, (shipsPlay1[shipsPlacedPlay1].rowStart+(segment*shipsPlay1[shipsPlacedPlay1].deltaRow)), (shipsPlay1[shipsPlacedPlay1].colStart+(segment*shipsPlay1[shipsPlacedPlay1].deltaCol))) > 0) {
overlapPlay1 = true;
break;
}
}
if (!overlapPlay1) {
// Messaggio posizionamento
MSG_SERIAL.print("BN_POS 1 ");
for (int segment=0; segment<shipsPlay1[shipsPlacedPlay1].numPieces; segment++) {
MSG_SERIAL.print(getCodeLed((shipsPlay1[shipsPlacedPlay1].rowStart+(segment*shipsPlay1[shipsPlacedPlay1].deltaRow)), (shipsPlay1[shipsPlacedPlay1].colStart+(segment*shipsPlay1[shipsPlacedPlay1].deltaCol))));
if ((segment+1)<shipsPlay1[shipsPlacedPlay1].numPieces) {
MSG_SERIAL.print(" ");
}
}
MSG_SERIAL.println("");
shipsPlacedPlay1++;
if (shipsPlacedPlay1 >= NUM_SHIPS) {
readyPlay1 = true;
turno = 2;
}
}
break;
default: //Non fare niente con gli altri tasti
break;
}
}
}
}
else {
if (autoPilotInitPlay1()) {
// Messaggio posizionamento
MSG_SERIAL.print("BN_POS 1 ");
for (int segment=0; segment<shipsPlay1[shipsPlacedPlay1].numPieces; segment++) {
MSG_SERIAL.print(getCodeLed((shipsPlay1[shipsPlacedPlay1].rowStart+(segment*shipsPlay1[shipsPlacedPlay1].deltaRow)), (shipsPlay1[shipsPlacedPlay1].colStart+(segment*shipsPlay1[shipsPlacedPlay1].deltaCol))));
if ((segment+1)<shipsPlay1[shipsPlacedPlay1].numPieces) {
MSG_SERIAL.print(" ");
}
}
MSG_SERIAL.println("");
shipsPlacedPlay1++;
if (shipsPlacedPlay1 >= NUM_SHIPS) {
readyPlay1 = true;
turno = 2;
}
}
if (btnPlay1[4].wasPressed()) {
btnPlay1[4].clearPressed();
autoPilotPlay1 = !autoPilotPlay1;
}
}
}
else {
ledStripTurnPlay1.setPixelColor(0, colorPlay2);
ledStripTurnPlay1.show();
}
// Controllo pressione tasto giocatore 2
if (!readyPlay2) {
if (!autoPilotPlay2) {
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasPressed()) {
btnPlay2[i].clearPressed();
switch(i) {
case 6: //Su
if ((shipsPlay2[shipsPlacedPlay2].rowStart) > 0) {
drawShip(&shipsPlay2[shipsPlacedPlay2], 0, 2);
shipsPlay2[shipsPlacedPlay2].rowStart--;
}
break;
case 5: //Giù
if (((shipsPlay2[shipsPlacedPlay2].rowStart)+(((shipsPlay2[shipsPlacedPlay2].numPieces)-1)*shipsPlay2[shipsPlacedPlay2].deltaRow)) < (NUM_ROWS-1)) {
drawShip(&shipsPlay2[shipsPlacedPlay2], 0, 2);
shipsPlay2[shipsPlacedPlay2].rowStart++;
}
break;
case 4: //Sinistra
if ((shipsPlay2[shipsPlacedPlay2].colStart) > 0) {
drawShip(&shipsPlay2[shipsPlacedPlay2], 0, 2);
shipsPlay2[shipsPlacedPlay2].colStart--;
}
break;
case 3: //Destra
if (((shipsPlay2[shipsPlacedPlay2].colStart)+(((shipsPlay2[shipsPlacedPlay2].numPieces)-1)*shipsPlay2[shipsPlacedPlay2].deltaCol)) < (NUM_COLS-1)) {
drawShip(&shipsPlay2[shipsPlacedPlay2], 0, 2);
shipsPlay2[shipsPlacedPlay2].colStart++;
}
break;
case 2:
autoPilotPlay2 = !autoPilotPlay2;
break;
case 1: //Ruota
drawShip(&shipsPlay2[shipsPlacedPlay2], 0, 2);
if (shipsPlay2[shipsPlacedPlay2].deltaRow > 0) {
shipsPlay2[shipsPlacedPlay2].deltaRow = 0;
shipsPlay2[shipsPlacedPlay2].deltaCol = 1;
if (((shipsPlay2[shipsPlacedPlay2].colStart)+(((shipsPlay2[shipsPlacedPlay2].numPieces)-1)*shipsPlay2[shipsPlacedPlay2].deltaCol)) > (NUM_COLS-1)) {
shipsPlay2[shipsPlacedPlay2].colStart = NUM_COLS - 1 - (((shipsPlay2[shipsPlacedPlay2].numPieces)-1)*shipsPlay2[shipsPlacedPlay2].deltaCol);
}
}
else {
shipsPlay2[shipsPlacedPlay2].deltaRow = 1;
shipsPlay2[shipsPlacedPlay2].deltaCol = 0;
if (((shipsPlay2[shipsPlacedPlay2].rowStart)+(((shipsPlay2[shipsPlacedPlay2].numPieces)-1)*shipsPlay2[shipsPlacedPlay2].deltaRow)) > (NUM_ROWS-1)) {
shipsPlay2[shipsPlacedPlay2].rowStart = NUM_ROWS - 1 - (((shipsPlay2[shipsPlacedPlay2].numPieces)-1)*shipsPlay2[shipsPlacedPlay2].deltaRow);
}
}
break;
case 0: //Piazza
// Controllo sovrapposizioni
overlapPlay2 = false;
for (int segment=0; segment<shipsPlay2[shipsPlacedPlay2].numPieces; segment++) {
if (checkShip(2, (shipsPlay2[shipsPlacedPlay2].rowStart+(segment*shipsPlay2[shipsPlacedPlay2].deltaRow)), (shipsPlay2[shipsPlacedPlay2].colStart+(segment*shipsPlay2[shipsPlacedPlay2].deltaCol))) > 0) {
overlapPlay2 = true;
break;
}
}
if (!overlapPlay2) {
// Messaggio posizionamento
MSG_SERIAL.print("BN_POS 2 ");
for (int segment=0; segment<shipsPlay2[shipsPlacedPlay2].numPieces; segment++) {
MSG_SERIAL.print(getCodeLed((shipsPlay2[shipsPlacedPlay2].rowStart+(segment*shipsPlay2[shipsPlacedPlay2].deltaRow)), (shipsPlay2[shipsPlacedPlay2].colStart+(segment*shipsPlay2[shipsPlacedPlay2].deltaCol))));
if ((segment+1)<shipsPlay2[shipsPlacedPlay2].numPieces) {
MSG_SERIAL.print(" ");
}
}
MSG_SERIAL.println("");
shipsPlacedPlay2++;
if (shipsPlacedPlay2 >= NUM_SHIPS) {
readyPlay2 = true;
turno = 1;
}
}
break;
default: //Non fare niente con gli altri tasti
break;
}
}
}
}
else {
if (autoPilotInitPlay2()) {
// Messaggio posizionamento
MSG_SERIAL.print("BN_POS 2 ");
for (int segment=0; segment<shipsPlay2[shipsPlacedPlay2].numPieces; segment++) {
MSG_SERIAL.print(getCodeLed((shipsPlay2[shipsPlacedPlay2].rowStart+(segment*shipsPlay2[shipsPlacedPlay2].deltaRow)), (shipsPlay2[shipsPlacedPlay2].colStart+(segment*shipsPlay2[shipsPlacedPlay2].deltaCol))));
if ((segment+1)<shipsPlay2[shipsPlacedPlay2].numPieces) {
MSG_SERIAL.print(" ");
}
}
MSG_SERIAL.println("");
shipsPlacedPlay2++;
if (shipsPlacedPlay2 >= NUM_SHIPS) {
readyPlay2 = true;
turno = 1;
}
}
if (btnPlay2[2].wasPressed()) {
btnPlay2[2].clearPressed();
autoPilotPlay2 = !autoPilotPlay2;
}
}
}
else {
ledStripTurnPlay2.setPixelColor(0, colorPlay1);
ledStripTurnPlay2.show();
}
if (readyPlay1 && readyPlay2) {
gameState = START_NB;
}
break;
case START_NB:
if (first) {
first = false;
ledStripTurnPlay1.clear();
ledStripTurnPlay2.clear();
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
memset(shotsPlay1, UNKNOWN, sizeof(enum shotStateEnum) * NUM_ROWS * NUM_COLS);
memset(shotsPlay2, UNKNOWN, sizeof(enum shotStateEnum) * NUM_ROWS * NUM_COLS);
DEBUG_SERIAL.println("START_NB");
}
if (animStartNB()) {
gameState = PLAY_MOVE_NB;
}
break;
case PLAY_MOVE_NB:
if (first) {
first = false;
ledStrip.clear();
ledStrip.show();
if (turno == 1) {
ledStripTurnPlay1.fill(colorPlay1);
ledStripTurnPlay2.fill(colorPlay1);
}
else {
ledStripTurnPlay1.fill(colorPlay2);
ledStripTurnPlay2.fill(colorPlay2);
}
ledStripTurnPlay1.show();
ledStripTurnPlay2.show();
row = NUM_ROWS/2;
col = NUM_COLS/2;
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
DEBUG_SERIAL.println("PLAY_MOVE_NB");
}
animPlayMoveNB(turno);
if (turno == 1) {
if (!autoPilotPlay1) {
// Controllo pressione tasto giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasReleased()) {
btnPlay1[i].clearReleased();
switch(i) {
case 0: //Su
if (row > 0) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
row--;
}
break;
case 1: //Giù
if (row < (NUM_ROWS-1)) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
row++;
}
break;
case 2: //Sinistra
if (col > 0) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
col--;
}
break;
case 3: //Destra
if (col < (NUM_COLS-1)) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
col++;
}
break;
case 4:
autoPilotPlay1 = !autoPilotPlay1;
break;
case 6: //Piazza
if ((shotsPlay1[row][col]) == UNKNOWN) {
outcomeAttack = updateShotsPlay(1);
// Messaggio seriale
MSG_SERIAL.print("BN 1 ");
MSG_SERIAL.print(getCodeLed(row, col));
if (outcomeAttack == WATER_BLINK) MSG_SERIAL.println(" ACQUA");
if (outcomeAttack == HIT_BLINK) MSG_SERIAL.println(" COLPITO");
if (outcomeAttack == SUNK_BLINK) MSG_SERIAL.println(" AFFONDATO");
gameState = ATTACK_NB;
}
break;
default: //Non fare niente
break;
}
}
}
}
else {
if (autoPilot(1)) {
outcomeAttack = updateShotsPlay(1);
// Messaggio seriale
MSG_SERIAL.print("BN 1 ");
MSG_SERIAL.print(getCodeLed(row, col));
if (outcomeAttack == WATER_BLINK) MSG_SERIAL.println(" ACQUA");
if (outcomeAttack == HIT_BLINK) MSG_SERIAL.println(" COLPITO");
if (outcomeAttack == SUNK_BLINK) MSG_SERIAL.println(" AFFONDATO");
gameState = ATTACK_NB;
}
if (btnPlay1[4].wasReleased()) {
btnPlay1[4].clearReleased();
autoPilotPlay1 = !autoPilotPlay1;
}
}
}
else {
if (!autoPilotPlay2) {
// Controllo pressione tasto giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasReleased()) {
btnPlay2[i].clearReleased();
switch(i) {
case 6: //Su
if (row > 0) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
row--;
}
break;
case 5: //Giù
if (row < (NUM_ROWS-1)) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
row++;
}
break;
case 4: //Sinistra
if (col > 0) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
col--;
}
break;
case 3: //Destra
if (col < (NUM_COLS-1)) {
ledStrip.setPixelColor(getNumLed(row, col, 1), 0);
ledStrip.setPixelColor(getNumLed(row, NUM_COLS-1-col, 2), 0);
col++;
}
break;
case 2:
autoPilotPlay2 = !autoPilotPlay2;
break;
case 0: //Piazza
if ((shotsPlay2[row][col]) == UNKNOWN) {
outcomeAttack = updateShotsPlay(2);
// Messaggio seriale
MSG_SERIAL.print("BN 2 ");
MSG_SERIAL.print(getCodeLed(row, col));
if (outcomeAttack == WATER_BLINK) MSG_SERIAL.println(" ACQUA");
if (outcomeAttack == HIT_BLINK) MSG_SERIAL.println(" COLPITO");
if (outcomeAttack == SUNK_BLINK) MSG_SERIAL.println(" AFFONDATO");
gameState = ATTACK_NB;
}
break;
default: //Non fare niente
break;
}
}
}
}
else {
if (autoPilot(2)) {
outcomeAttack = updateShotsPlay(2);
// Messaggio seriale
MSG_SERIAL.print("BN 2 ");
MSG_SERIAL.print(getCodeLed(row, col));
if (outcomeAttack == WATER_BLINK) MSG_SERIAL.println(" ACQUA");
if (outcomeAttack == HIT_BLINK) MSG_SERIAL.println(" COLPITO");
if (outcomeAttack == SUNK_BLINK) MSG_SERIAL.println(" AFFONDATO");
gameState = ATTACK_NB;
}
if (btnPlay2[2].wasReleased()) {
btnPlay2[2].clearReleased();
autoPilotPlay2 = !autoPilotPlay2;
}
}
}
break;
case ATTACK_NB:
if (first) {
first = false;
scorePlay1 = 0;
scorePlay2 = 0;
DEBUG_SERIAL.println("ATTACK_NB");
}
if (animAttackNB(turno)) {
gameState = CHECK_WIN_NB;
}
break;
case CHECK_WIN_NB:
if (first) {
first = false;
DEBUG_SERIAL.println("CHECK_WIN_NB");
}
if (checkWinNB(turno)) {
MSG_SERIAL.print("BN_WIN ");
MSG_SERIAL.print(turno);
gameState = WIN_NB;
}
else {
if (turno == 1) {
turno = 2;
}
else {
turno = 1;
}
gameState = PLAY_MOVE_NB;
}
break;
case WIN_NB:
if (first) {
first = false;
DEBUG_SERIAL.println("WIN_NB");
}
if (animWinNB()) {
gameState = FINISH_NB;
}
break;
case FINISH_NB:
if (first) {
first = false;
clearBtnsPlay1AllEvents();
clearBtnsPlay2AllEvents();
DEBUG_SERIAL.println("FINISH_NB");
}
// Controllo pressione tasto giocatore 1
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay1[i].wasPressed()) {
btnPlay1[i].clearPressed();
gameState = INIT_NB;
}
}
// Controllo pressione tasto giocatore 2
for (int i=0; i<NUM_COLS; i++) {
if (btnPlay2[i].wasPressed()) {
btnPlay2[i].clearPressed();
gameState = INIT_NB;
}
}
break;
default:
break;
}
}