/* This method handles the move of fire type. depending on the direction of the beam, either a piece is captured or the beam is reflected untill it moves off the board */ void Board::handleFireMove(uint32_t orig_r, uint32_t orig_c, Piece::Orientation beam_ori, uint32_t depth) { if (depth > 20) return; Piece* first_hit = findFirstPieceHit(orig_r, orig_c, beam_ori); // check if laser hits a piece if (first_hit) { if (first_hit->ptype == Piece::HYPER_HOLE) return; else if (!first_hit->can_reflect(beam_ori)) deletePiece(first_hit); else { // generate reflected beam std::list<Piece::Orientation> ori_list; first_hit->getReflectedOrientations(beam_ori, ori_list); std::list<Piece::Orientation>::iterator or_it; for (or_it=ori_list.begin(); or_it != ori_list.end(); or_it++) { handleFireMove(first_hit->pos.row, first_hit->pos.col, *or_it, depth+1); } } } }
/* * Moves the piece to rigth with collision detection * moving a piece is just a shift of the 4 chars of the piece */ void goRigth() { /* * try to move piece only if it still fits in the field after rotation * the trick is check if one of the less significant bits of each char is equal to 1 */ if (((actualPiece[0] | actualPiece[1] | actualPiece[2] | actualPiece[3]) & 0x01) == 0x00) { /* * first deletes the actual piece from the field and then * checks is there is no collision with the new position. if the * piece fits beetween the other pieces adds it to fild. else retores the original * piece if collides with other pieces */ deletePiece(); // deletes the actual piece from field updateTempPiece(); // updates temp piece shiftRigth(tempPiece); // shifts the temp piece if (isCollision() == 0x00) { // no collision? shifts the actual piece shiftRigth(actualPiece); // and adds it to the field addPiece(); updateTempPiece(); pieceShift++; } addPiece(); // no collision? replace the actual piece on field updateDisplayField(); // updates the display field } }
/* * Rotates the actual piece CCW with collision detection * the rotation is just a piece layout change with the actual piecePos, * rotates only if is possible. */ void rotate() { char i = 0; // try to rotate piece only if it still fits in the field after rotation if (pieceNum != 0x00 && getMaxLeftShift() <= pieceShift && pieceShift <= getMaxRigthShift()) { /* * first deletes the actual piece from the field and then * checks is there is no collision with the new position. if the * piece fits beetween the other pieces adds it to fild. else retores the original * piece if collides with other pieces */ deletePiece(); // deletes the actual piece from field piecePos++; // increments the piece y position if (piecePos == 0x04) { // controls the rotation position range piecePos = 0x00; } tempPiece[0] = pieces[pieceNum][piecePos][0]; // updates the temp piece tempPiece[1] = pieces[pieceNum][piecePos][1]; tempPiece[2] = pieces[pieceNum][piecePos][2]; tempPiece[3] = pieces[pieceNum][piecePos][3]; if (pieceShift < 0x00) { // shifts the temp piece to actal x position for (i = (-1) * pieceShift; i > 0; i--) { shiftLeft(tempPiece); } } else { for (i = pieceShift; i > 0; i--) { shiftRigth(tempPiece); } } if (isCollision() == 0x00) { // no collision? aplies the new rotation position actualPiece[0] = pieces[pieceNum][piecePos][0]; actualPiece[1] = pieces[pieceNum][piecePos][1]; actualPiece[2] = pieces[pieceNum][piecePos][2]; actualPiece[3] = pieces[pieceNum][piecePos][3]; // shifts the new piece to the last X position if (pieceShift < 0x00) { for (i = (-1) * pieceShift; i > 0; i--) { shiftLeft(actualPiece); } } else { for (i = pieceShift; i > 0; i--) { shiftRigth(actualPiece); } } } else { // collision? just go back and aplies the last piece if (piecePos == 0x00) { piecePos = 0x03; } else { piecePos--; } } addPiece(); updateDisplayField(); // updates the display field } }
void Board::applyMove(Move* m) { if (m->isMove()) { /* Move moves */ int32_t dst_r, dst_c; // get the destination row and column value for given move m->getPieceDestination(dst_r, dst_c); // get the current piece at the move source point Piece* p = piece_array[m->piece_r][m->piece_c]; // dst is occupied by another piece of either colour if (piece_array[dst_r][dst_c] != NULL) { Piece* dst_p = piece_array[dst_r][dst_c]; // dst is hyperhole if (dst_p->ptype == Piece::HYPER_HOLE) { if (!m->tport_info) { do { // find a random unoccupied position p->teleportRandom(); } while (piece_array[p->pos.row][p->pos.col] != NULL); // store teleport info m->tport_info = new Move::TeleportInfo(p->pos.row, p->pos.col, p->ori); } else { Move::TeleportInfo* t = m->tport_info; p->pos.row = t->row; p->pos.col = t->col; p->ori = t->ori; } // update p info piece_array[p->pos.row][p->pos.col] = p; piece_array[m->piece_r][m->piece_c] = NULL; return; } else if (p->ptype == Piece::HYPERCUBE) { // piece is hypercube if (!m->tport_info) { do { // find a random unoccupied position dst_p->teleportRandom(); } while (piece_array[dst_p->pos.row][dst_p->pos.col] != NULL); m->tport_info = new Move::TeleportInfo(dst_p->pos.row, dst_p->pos.col, dst_p->ori); // fprintf(stderr, "Stored for %p\n", m); // m->printMove(); } else { // fprintf(stderr, "getting %p\n", m); // m->printMove(); Move::TeleportInfo* t = m->tport_info; dst_p->pos.row = t->row; dst_p->pos.col = t->col; dst_p->ori = t->ori; } // update dst_p info piece_array[dst_p->pos.row][dst_p->pos.col] = dst_p; } else { // we capture piece deletePiece(dst_p); } } // move piece into position and set original to NULL piece_array[dst_r][dst_c] = p; piece_array[m->piece_r][m->piece_c] = NULL; // update piece_position p->pos.row = dst_r; p->pos.col = dst_c; } else if (m->isFire()) { /* Fire moves */ Piece* p = piece_array[m->piece_r][m->piece_c]; handleFireMove(m->piece_r, m->piece_c, p->ori); } else if (m->isRotate()) { /* Rotate moves */ Piece* p = piece_array[m->piece_r][m->piece_c]; switch (m->m_typ) { case ROTATE_C: p->rotate_c(); break; case ROTATE_AC: p->rotate_ac(); break; default: assert(false && "Shouldn't be here"); } } }