void StackZone::reorganizeCards() { if (!cards.isEmpty()) { QList<ArrowItem *> arrowsToUpdate; const int cardCount = cards.size(); qreal totalWidth = boundingRect().width(); qreal totalHeight = boundingRect().height(); qreal cardWidth = cards.at(0)->boundingRect().width(); qreal cardHeight = cards.at(0)->boundingRect().height(); qreal xspace = 5; qreal x1 = xspace; qreal x2 = totalWidth - xspace - cardWidth; for (int i = 0; i < cardCount; i++) { CardItem *c = cards.at(i); qreal x = i % 2 ? x2 : x1; // If the total height of the cards is smaller than the available height, // the cards do not need to overlap and are displayed in the center of the area. if (cardHeight * cardCount > totalHeight) c->setPos(x, ((qreal) i) * (totalHeight - cardHeight) / (cardCount - 1)); else c->setPos(x, ((qreal) i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2); c->setRealZValue(i); arrowsToUpdate.append(c->getArrowsFrom()); arrowsToUpdate.append(c->getArrowsTo()); } QSetIterator<ArrowItem *> arrowIterator(QSet<ArrowItem *>::fromList(arrowsToUpdate)); while (arrowIterator.hasNext()) arrowIterator.next()->updatePath(); } update(); }
ResponseCode Server_ProtocolHandler::cmdCreateArrow(Command_CreateArrow *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { if (player->getSpectator()) return RespFunctionNotAllowed; if (!game->getGameStarted()) return RespGameNotStarted; Server_Player *startPlayer = game->getPlayer(cmd->getStartPlayerId()); Server_Player *targetPlayer = game->getPlayer(cmd->getTargetPlayerId()); if (!startPlayer || !targetPlayer) return RespNameNotFound; Server_CardZone *startZone = startPlayer->getZones().value(cmd->getStartZone()); bool playerTarget = cmd->getTargetZone().isEmpty(); Server_CardZone *targetZone = 0; if (!playerTarget) targetZone = targetPlayer->getZones().value(cmd->getTargetZone()); if (!startZone || (!targetZone && !playerTarget)) return RespNameNotFound; if (startZone->getType() != PublicZone) return RespContextError; Server_Card *startCard = startZone->getCard(cmd->getStartCardId(), false); if (!startCard) return RespNameNotFound; Server_Card *targetCard = 0; if (!playerTarget) { if (targetZone->getType() != PublicZone) return RespContextError; targetCard = targetZone->getCard(cmd->getTargetCardId(), false); } Server_ArrowTarget *targetItem; if (playerTarget) targetItem = targetPlayer; else targetItem = targetCard; if (!targetItem) return RespNameNotFound; QMapIterator<int, Server_Arrow *> arrowIterator(player->getArrows()); while (arrowIterator.hasNext()) { Server_Arrow *temp = arrowIterator.next().value(); if ((temp->getStartCard() == startCard) && (temp->getTargetItem() == targetItem)) return RespContextError; } Server_Arrow *arrow = new Server_Arrow(player->newArrowId(), startCard, targetItem, cmd->getColor()); player->addArrow(arrow); game->sendGameEvent(new Event_CreateArrows(player->getPlayerId(), QList<ServerInfo_Arrow *>() << new ServerInfo_Arrow( arrow->getId(), startPlayer->getPlayerId(), startZone->getName(), startCard->getId(), targetPlayer->getPlayerId(), cmd->getTargetZone(), cmd->getTargetCardId(), cmd->getColor() ))); return RespOk; }
void TableZone::reorganizeCards() { QList<ArrowItem *> arrowsToUpdate; // Calculate card stack widths so mapping functions work properly computeCardStackWidths(); for (int i = 0; i < cards.size(); ++i) { QPoint gridPoint = cards[i]->getGridPos(); if (gridPoint.x() == -1) continue; QPointF mapPoint = mapFromGrid(gridPoint); qreal x = mapPoint.x(); qreal y = mapPoint.y(); int numberAttachedCards = cards[i]->getAttachedCards().size(); qreal actualX = x + numberAttachedCards * STACKED_CARD_OFFSET_X; qreal actualY = y; if (numberAttachedCards) actualY += 15; cards[i]->setPos(actualX, actualY); cards[i]->setRealZValue((actualY + CARD_HEIGHT) * 100000 + (actualX + 1) * 100); QListIterator<CardItem *> attachedCardIterator(cards[i]->getAttachedCards()); int j = 0; while (attachedCardIterator.hasNext()) { ++j; CardItem *attachedCard = attachedCardIterator.next(); qreal childX = actualX - j * STACKED_CARD_OFFSET_X; qreal childY = y + 5; attachedCard->setPos(childX, childY); attachedCard->setRealZValue((childY + CARD_HEIGHT) * 100000 + (childX + 1) * 100); arrowsToUpdate.append(attachedCard->getArrowsFrom()); arrowsToUpdate.append(attachedCard->getArrowsTo()); } arrowsToUpdate.append(cards[i]->getArrowsFrom()); arrowsToUpdate.append(cards[i]->getArrowsTo()); } QSetIterator<ArrowItem *> arrowIterator(QSet<ArrowItem *>::fromList(arrowsToUpdate)); while (arrowIterator.hasNext()) arrowIterator.next()->updatePath(); resizeToContents(); update(); }
void Server_Player::clearZones() { QMapIterator<QString, Server_CardZone *> zoneIterator(zones); while (zoneIterator.hasNext()) delete zoneIterator.next().value(); zones.clear(); QMapIterator<int, Server_Counter *> counterIterator(counters); while (counterIterator.hasNext()) delete counterIterator.next().value(); counters.clear(); QMapIterator<int, Server_Arrow *> arrowIterator(arrows); while (arrowIterator.hasNext()) delete arrowIterator.next().value(); arrows.clear(); }
ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *startzone, const QList<int> &_cardIds, Server_CardZone *targetzone, int x, int y, bool faceDown, bool tapped) { // Disallow controller change to other zones than the table. if (((targetzone->getType() != PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer())) return RespContextError; if (!targetzone->hasCoords() && (x == -1)) x = targetzone->cards.size(); QList<QPair<Server_Card *, int> > cardsToMove; for (int i = 0; i < _cardIds.size(); ++i) { int position; Server_Card *card = startzone->getCard(_cardIds[i], false, &position); if (!card) return RespNameNotFound; if (!card->getAttachedCards().isEmpty() && !targetzone->isColumnEmpty(x, y)) return RespContextError; cardsToMove.append(QPair<Server_Card *, int>(card, position)); } MoveCardCompareFunctor cmp(startzone == targetzone ? -1 : x); qSort(cardsToMove.begin(), cardsToMove.end(), cmp); bool secondHalf = false; int xIndex = -1; for (int cardIndex = 0; cardIndex < cardsToMove.size(); ++cardIndex) { Server_Card *card = cardsToMove[cardIndex].first; int originalPosition = cardsToMove[cardIndex].second; int position = startzone->removeCard(card); if ((startzone == targetzone) && !startzone->hasCoords()) { if (!secondHalf && (originalPosition < x)) { xIndex = -1; secondHalf = true; } else if (secondHalf) --xIndex; else ++xIndex; } else ++xIndex; int newX = x + xIndex; // Attachment relationships can be retained when moving a card onto the opponent's table if (startzone->getName() != targetzone->getName()) { // Delete all attachment relationships if (card->getParentCard()) card->setParentCard(0); // Make a copy of the list because the original one gets modified during the loop QList<Server_Card *> attachedCards = card->getAttachedCards(); for (int i = 0; i < attachedCards.size(); ++i) attachedCards[i]->getZone()->getPlayer()->unattachCard(cont, attachedCards[i]); } if (startzone != targetzone) { // Delete all arrows from and to the card const QList<Server_Player *> &players = game->getPlayers().values(); for (int i = 0; i < players.size(); ++i) { QList<int> arrowsToDelete; QMapIterator<int, Server_Arrow *> arrowIterator(players[i]->getArrows()); while (arrowIterator.hasNext()) { Server_Arrow *arrow = arrowIterator.next().value(); if ((arrow->getStartCard() == card) || (arrow->getTargetItem() == card)) arrowsToDelete.append(arrow->getId()); } for (int j = 0; j < arrowsToDelete.size(); ++j) players[i]->deleteArrow(arrowsToDelete[j]); } } if (card->getDestroyOnZoneChange() && (startzone != targetzone)) { cont->enqueueGameEventPrivate(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId()); cont->enqueueGameEventPublic(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId()); card->deleteLater(); } else { if (!targetzone->hasCoords()) { y = 0; card->resetState(); } else newX = targetzone->getFreeGridColumn(newX, y, card->getName()); targetzone->insertCard(card, newX, y); bool targetBeingLookedAt = (targetzone->getType() != HiddenZone) || (targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1); bool sourceBeingLookedAt = (startzone->getType() != HiddenZone) || (startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1); bool targetHiddenToPlayer = faceDown || !targetBeingLookedAt; bool targetHiddenToOthers = faceDown || (targetzone->getType() != PublicZone); bool sourceHiddenToPlayer = card->getFaceDown() || !sourceBeingLookedAt; bool sourceHiddenToOthers = card->getFaceDown() || (startzone->getType() != PublicZone); QString privateCardName, publicCardName; if (!(sourceHiddenToPlayer && targetHiddenToPlayer)) privateCardName = card->getName(); if (!(sourceHiddenToOthers && targetHiddenToOthers)) publicCardName = card->getName(); int oldCardId = card->getId(); if (faceDown) card->setId(newCardId()); card->setFaceDown(faceDown); // The player does not get to see which card he moved if it moves between two parts of hidden zones which // are not being looked at. int privateNewCardId = card->getId(); int privateOldCardId = oldCardId; if (!targetBeingLookedAt && !sourceBeingLookedAt) { privateOldCardId = -1; privateNewCardId = -1; privateCardName = QString(); } int privatePosition = -1; if (startzone->getType() == HiddenZone) privatePosition = position; cont->enqueueGameEventPrivate(new Event_MoveCard(getPlayerId(), privateOldCardId, privateCardName, startzone->getName(), privatePosition, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, privateNewCardId, faceDown), game->getGameId()); cont->enqueueGameEventOmniscient(new Event_MoveCard(getPlayerId(), privateOldCardId, privateCardName, startzone->getName(), privatePosition, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, privateNewCardId, faceDown), game->getGameId()); // Other players do not get to see the start and/or target position of the card if the respective // part of the zone is being looked at. The information is not needed anyway because in hidden zones, // all cards are equal. if ( ((startzone->getType() == HiddenZone) && ((startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1))) || (startzone->getType() == PublicZone) ) position = -1; if ((targetzone->getType() == HiddenZone) && ((targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1))) newX = -1; if ((startzone->getType() == PublicZone) || (targetzone->getType() == PublicZone)) cont->enqueueGameEventPublic(new Event_MoveCard(getPlayerId(), oldCardId, publicCardName, startzone->getName(), position, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, card->getId(), faceDown), game->getGameId()); else cont->enqueueGameEventPublic(new Event_MoveCard(getPlayerId(), -1, QString(), startzone->getName(), position, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, -1, false), game->getGameId()); if (tapped) setCardAttrHelper(cont, targetzone->getName(), card->getId(), "tapped", "1"); } } if (startzone->hasCoords()) startzone->fixFreeSpaces(cont); return RespOk; }
void TableZone::reorganizeCards() { QList<ArrowItem *> arrowsToUpdate; // Calculate table grid distortion so that the mapping functions work properly QMap<int, int> gridPointStackCount; for (int i = 0; i < cards.size(); ++i) { const QPoint &gridPoint = cards[i]->getGridPos(); if (gridPoint.x() == -1) continue; const int key = gridPoint.x() / 3 + gridPoint.y() * 1000; gridPointStackCount.insert(key, gridPointStackCount.value(key, 0) + 1); } gridPointWidth.clear(); for (int i = 0; i < cards.size(); ++i) { const QPoint &gridPoint = cards[i]->getGridPos(); if (gridPoint.x() == -1) continue; const int key = gridPoint.x() / 3 + gridPoint.y() * 1000; const int stackCount = gridPointStackCount.value(key, 0); if (stackCount == 1) gridPointWidth.insert(key, CARD_WIDTH * (1 + cards[i]->getAttachedCards().size() / 3.0)); else gridPointWidth.insert(key, CARD_WIDTH * (1 + (stackCount - 1) / 3.0)); } for (int i = 0; i < cards.size(); ++i) { QPoint gridPoint = cards[i]->getGridPos(); if (gridPoint.x() == -1) continue; QPointF mapPoint = mapFromGrid(gridPoint); qreal x = mapPoint.x(); qreal y = mapPoint.y(); int numberAttachedCards = cards[i]->getAttachedCards().size(); qreal actualX = x + numberAttachedCards * CARD_WIDTH / 3.0; qreal actualY = y; if (numberAttachedCards) actualY += 15; cards[i]->setPos(actualX, actualY); cards[i]->setRealZValue((actualY + CARD_HEIGHT) * 100000 + (actualX + 1) * 100); QListIterator<CardItem *> attachedCardIterator(cards[i]->getAttachedCards()); int j = 0; while (attachedCardIterator.hasNext()) { ++j; CardItem *attachedCard = attachedCardIterator.next(); qreal childX = actualX - j * CARD_WIDTH / 3.0; qreal childY = y + 5; attachedCard->setPos(childX, childY); attachedCard->setRealZValue((childY + CARD_HEIGHT) * 100000 + (childX + 1) * 100); arrowsToUpdate.append(attachedCard->getArrowsFrom()); arrowsToUpdate.append(attachedCard->getArrowsTo()); } arrowsToUpdate.append(cards[i]->getArrowsFrom()); arrowsToUpdate.append(cards[i]->getArrowsTo()); } QSetIterator<ArrowItem *> arrowIterator(QSet<ArrowItem *>::fromList(arrowsToUpdate)); while (arrowIterator.hasNext()) arrowIterator.next()->updatePath(); resizeToContents(); update(); }