/** * Move nb_pawns of the player p from the cell src_cell to the cell dst_cell * * Check if dst and src are neighbours * error if not * check dst owner * if owner == p or null * move pawns * else * fight * if not draw (no move) * remove pawns from src. * * return move result (nofight, draw, win, lost) */ short player_move_to_cell(s_player *p, uint16_t nb_pawns, struct s_cell *src_cell, struct s_cell *dst_cell) { short result; if (nb_pawns > p->nb_pawns) return PLAYER_ERROR_MOVE_NOT_ENOUGH_PAWNS; else if (nb_pawns >= src_cell->nb_pawns) return PLAYER_ERROR_MOVE_ALL_PAWNS; if (!cell_are_neighbours(src_cell, dst_cell)) { return PLAYER_ERROR_MOVE_CELLS_NOT_NEIGHBOURS; } if (dst_cell->owner != NULL && dst_cell->owner->id != p->id) { // fight result = _fight(nb_pawns, dst_cell); } else { if (dst_cell->owner == NULL) { dst_cell->owner = p; p->nb_cells++; } dst_cell->nb_pawns = (uint16_t) (dst_cell->nb_pawns + nb_pawns); result = NO_FIGHT; } if (result != FIGHT_DRAW) { src_cell->nb_pawns = (uint16_t) (src_cell->nb_pawns - nb_pawns); if (result == FIGHT_LOST) { p->nb_pawns = (uint16_t) (p->nb_pawns - nb_pawns); } else if (result == FIGHT_WON) { // update opponent pawns and cells number dst_cell->owner->nb_pawns = (uint16_t) (dst_cell->owner->nb_pawns - dst_cell->nb_pawns); dst_cell->owner->nb_cells--; // update cell owner dst_cell->owner = p; dst_cell->nb_pawns = nb_pawns; p->nb_cells = (uint8_t) (p->nb_cells + 1); } } return result; }
/** Primary state machine for ninja fight game handles exchange of packets and setting up game between the two players */ static void _doNinja(NinjaState *state, NinjaPacket *packet) { uint32_t endTime = 0; //Init the game state state->p1Idle1 = getBitmapMetadata(NINJA_P1_IDLE1_address); state->p2Idle1 = getBitmapMetadata(NINJA_P2_IDLE1_address); state->p1Idle2 = getBitmapMetadata(NINJA_P1_IDLE2_address); state->p2Idle2 = getBitmapMetadata(NINJA_P2_IDLE2_address); state->p1Punch1 = getBitmapMetadata(NINJA_P1_PUNCH1_address); state->p2Punch1 = getBitmapMetadata(NINJA_P2_PUNCH1_address); state->p1Punch2 = getBitmapMetadata(NINJA_P1_PUNCH2_address); state->p2Punch2 = getBitmapMetadata(NINJA_P2_PUNCH2_address); state->p1Kick1 = getBitmapMetadata(NINJA_P1_KICK1_address); state->p2Kick1 = getBitmapMetadata(NINJA_P2_KICK1_address); state->p1Kick2 = getBitmapMetadata(NINJA_P1_KICK2_address); state->p2Kick2 = getBitmapMetadata(NINJA_P2_KICK2_address); state->p1Shield1 = getBitmapMetadata(NINJA_P1_SHIELD1_address); state->p2Shield1 = getBitmapMetadata(NINJA_P2_SHIELD1_address); state->p1Shield2 = getBitmapMetadata(NINJA_P1_SHIELD2_address); state->p2Shield2 = getBitmapMetadata(NINJA_P2_SHIELD2_address); state->p1Dead = getBitmapMetadata(NINJA_P1_DEAD_address); state->p2Dead = getBitmapMetadata(NINJA_P2_DEAD_address); state->troll = getBitmapMetadata(NINJA_DT_address); state->punch = getBitmapMetadata(NINJA_PUNCH_address); state->kick = getBitmapMetadata(NINJA_KICK_address); state->shield = getBitmapMetadata(NINJA_SHIELD_address); state->up = getBitmapMetadata(NINJA_UP_address); state->down = getBitmapMetadata(NINJA_DOWN_address); state->right = getBitmapMetadata(NINJA_RIGHT_address); state->state = STATE_SELECT_MOVE; state->round = 1; state->p1Score = 0; state->p2Score = 0; while (state->p1Score < 2 && state->p2Score < 2) { if (state->state == STATE_SELECT_MOVE) { state->lastACK = -1; //Set p2Move to -1 *before* _getPlayerMove (which could change it!) state->p2Move = -1; //other player move state->p1Move = _getPlayerMove(state, packet); endTime = rtMillis() + 20000; bool ackRecv = false; bool moveRecv = false; //Wait for a bit sending and receiving until we're synced with other player while (state->lastACK != TYPE_MOVE || state->p2Move < 0) { //Show a dialog to the player char wait[32]; sprintf(wait, "Waiting for\nplayer %d", (endTime - rtMillis()) / 1000); statusDialog(wait); safeDisplay(); //Keep sending until an ACK is received if (state->lastACK != TYPE_MOVE) { //Fill out the rest of the packet packet->type = TYPE_MOVE; packet->data = state->p1Move; packet->round = state->round; ANXRFSend(packet, NINJA_PACKET_SIZE); } //Delay and do some ticking (400ms) for (uint8_t i = 0; i < 16; i++) { deepSleep(25); tick(); //Process any data that comes in _handlePackets(state, packet); } //give up on other player if (rtMillis() > endTime) { state->state = STATE_ABORT; break; } } //Bump them over to fight if (state->state != STATE_ABORT) state->state = STATE_FIGHT; } else if (state->state == STATE_FIGHT) { _fight(state, packet); state->state = STATE_SELECT_MOVE; state->round++; } else if (state->state == STATE_ABORT) { break; } deepSleep(200); tick(); } _gameOver(state); enablePopups(); }