From ce48af53646cd9e7ec762fc1ac176b3aa620b11d Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 5 May 2011 00:57:07 +0200 Subject: - refactorized the whole project and made a few subprojects - replaced tcp with enet - added connect dialog - some smaller bugfixes --- pacman-c++/server.cpp | 900 -------------------------------------------------- 1 file changed, 900 deletions(-) delete mode 100644 pacman-c++/server.cpp (limited to 'pacman-c++/server.cpp') diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp deleted file mode 100644 index 2311c81..0000000 --- a/pacman-c++/server.cpp +++ /dev/null @@ -1,900 +0,0 @@ -#include "server.h" -#include "util.h" -#include "pacman.pb.h" -#include "block.h" -#include "anyoption.h" -#include "bonuspoint.h" -#include "point.h" -#include -#include -#include -#include - -Server::Server(QWidget *parent) - : SceneHolder(parent), m_bindaddress(QHostAddress::Any), - m_port(Constants::Networking::port), m_numbots(0), - m_rounds(3), m_curRound(0), m_running(false), m_finishRound(false) -{ - /* determine max players by using order array */ - for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers); -} - -bool Server::run() -{ - /* create eating order list first - this can also be created dynamically per round (theoretically) */ - for(unsigned int i = 0; i < m_maxplayers; ++i) - m_eatingorder.append(Color::order[i]); - m_eatingorder.append(m_eatingorder.at(0)); - - m_tickTimer = new QTimer(this); - m_tickTimer->setInterval(Constants::tick); - connect(m_tickTimer, SIGNAL(timeout()), this, SLOT(tick())); - - std::cout << "[Server] Running server..." << std::endl - << "[Server] Max players: " << m_maxplayers << std::endl - << "[Server] Number of bots: " << m_numbots << std::endl - << "[Server] Number of rounds: " << m_rounds << std::endl; - if (!waitForClientConnections()) - return false; - - connect(this, SIGNAL(allPointsRemoved()), this, SLOT(setFinishRound())); - initRoundMap(); - return true; -} - -void Server::tick() -{ - //qDebug() << "[Tick] Doing server update"; - if (m_finishRound) - stopGame(true); - if (!m_running) - { - Transmission::map_t map = Util::createEmptyMap(); - sendUpdate(map); - Util::deleteMap(map); - return; - } - - /* let the bots move */ - foreach (Color::Color color, m_bots) - botCalculate(m_actors[color]); - - /* move on the virtual map */ - Transmission::map_t map = calculateUpdates(); - updateMap(map); - - /* add a random bonus point */ - QPoint pos = addRandomPoint(map, Transmission::bonuspoint); - if (!pos.isNull()) - updateMap(map, pos.x(), pos.y()); - - /* add/remove random colorized block */ - if (this->property("coloredblocks").toBool()) - colorizeBlocks(map); - - sendUpdate(map); - Util::deleteMap(map); -} - -Transmission::map_t Server::calculateUpdates() -{ - QMap > movements; - Transmission::map_t map = Util::createEmptyMap(); - - QMutableMapIterator i(m_actorMovements); - while (i.hasNext()) - { - i.next(); - Color::Color color = i.key(); - Actor *actor = m_actors[color]; - QPoint mapPosition = CoordToMapPosition(actor->pos().toPoint()); - Actor::Movement direction = i.value(); - int turn = 0; - -invalid_direction: - ++turn; - qDebug() << "[Calc] Actor wants to move: color=" << color - << "pos=" << mapPosition << "direction=" << direction; - - QPoint newMapPosition = mapPosition + Actor::movementToPoint(direction); - if (newMapPosition.x() < 0) - newMapPosition.setX(0); - if (newMapPosition.x() >= visualMap.size()) - newMapPosition.setX(visualMap.size() - 1); - if (newMapPosition.y() < 0) - newMapPosition.setY(0); - if (newMapPosition.y() >= visualMap[newMapPosition.x()].size()) - newMapPosition.setY(visualMap[newMapPosition.x()].size() - 1); - - /* check if there's an item at new location of actor */ - GameEntity *item = visualMap[newMapPosition.x()][newMapPosition.y()]; - GameEntity *oldItem = visualMap[mapPosition.x()][mapPosition.y()]; - if (item != NULL && oldItem != item) - { - qDebug() << "[Calc] Found item at new actor location"; - if (!item->checkEnter(actor)) - { - /* movement invalid. e.g. move against wall */ - newMapPosition = mapPosition; - qDebug() << "[Calc] Item blocks actor"; - } - else - { - /* apply actions of entering this field */ - GameEntity::EnteredState survive = item->enter(actor); - if (survive == GameEntity::DestroyedEntity) - map[newMapPosition.x()][newMapPosition.y()] = Transmission::empty | actor->color(); - else if (survive == GameEntity::DestroyedActor) - { - map[newMapPosition.x()][newMapPosition.y()] = Transmission::death | actor->color(); - m_actors[item->color()]->addRoundPoints(actor->getRoundPoints()); - actor->finishRound(true); - setFinishRound(); - } - } - } - - /* movement didn't work - e.g. was blocked */ - if (mapPosition == newMapPosition) - { - /* check turn */ - if (turn == 1 && direction != actor->direction()) - { - /* set direction back to last known direction and try again */ - qDebug() << "[Calc] Movement was blocked. Trying last known actor direction"; - direction = actor->direction(); - goto invalid_direction; - } - else - { - /* second turn didn't work too -> stop movement */ - direction = Actor::None; - qDebug() << "[Calc] No good direction known. Movement stopped"; - } - } - - /* store movement for collision */ - movements.insert(color, QPair(mapPosition, newMapPosition)); - - /* set direction (used for collision detection) */ - actor->setDirection(direction); - - /* DEBUG: uncomments to disable auto-movement */ - //direction = Actor::None; - - /* actor is not moving anymore: remove from list */ - if (direction == Actor::None) - i.remove(); - } - - /* check for actor collision */ - QList blocked; - foreach(Color::Color color, movements.keys()) - { - Actor *actor = m_actors[color]; - QPoint oldpos = movements[color].first; - QPoint newpos = movements[color].second; - QPoint scenepos = actor->pos().toPoint(); - - /* first move actor to new position */ - actor->move(actor->direction()); - - /* next check for collisions */ - Actor *orderer = NULL; - Actor *meal = NULL; - foreach(Actor *other, m_actors) - { - if (actor == other) - continue; - if (!actor->collidesWithItem(other)) - continue; - /* both move in the same direction */ - if (actor->direction() == other->direction()) - continue; - - if (other->canEat(actor, m_eatingorder)) - { - qDebug() << "[Collision] Actor" << actor->color() << "got EATEN by" << other->color(); - orderer = other; - meal = actor; - break; - } - else if (actor->canEat(other, m_eatingorder)) - { - qDebug() << "[Collision] Actor" << actor->color() << "EATS" << other->color(); - orderer = actor; - meal = other; - blocked.append(other); - break; - } - else - { - qDebug() << "[Collision] Actor" << actor->color() << "got BLOCKED by" << other->color(); - blocked.append(actor); - /* no break here */ - } - } - - /* update map depending on collision */ - if (orderer != NULL && meal != NULL) - { - map[newpos.x()][newpos.y()] |= Transmission::pacman | Transmission::death - | orderer->color() | meal->color(); - orderer->addRoundPoints(meal->getRoundPoints()); - meal->finishRound(true); - setFinishRound(); - } - else if (blocked.contains(actor)) - { - /* move actor back early cause he won't move */ - actor->setPos(scenepos); - map[oldpos.x()][oldpos.y()] |= Transmission::pacman | color; - } - else - { - map[newpos.x()][newpos.y()] |= Transmission::pacman | color; - } - } - - /* move all actors back to their origin position */ - foreach(Color::Color color, movements.keys()) - m_actors[color]->setPos(mapPositionToCoord(movements[color].first)); - -#ifndef QT_NO_DEBUG - /* collision sanity check: colors must be unique */ - foreach(Color::Color col, m_eatingorder.toSet()) - { - QList found; - for (unsigned int x = 0; x < Constants::map_size.width; ++x) - { - for (unsigned int y = 0; y < Constants::map_size.height; ++y) - { - if ((map[x][y] & Transmission::color_mask) & col) - found.append(QPoint(x, y)); - } - } - if (found.count() > 1) - qCritical() << "[Collision] found" << found.count() << "fields with color=" << col; - } -#endif - - return map; -} - -QPoint Server::addRandomPoint(Transmission::map_t map, Transmission::field_t type) -{ - int chance = Constants::Game::bouns_point_chance - - Constants::Game::bouns_point_chance_playerfactor * (m_maxplayers - 1); - int rand = (int) (chance * (qrand() / (RAND_MAX + 1.0))); - if (rand != 0) - return QPoint(); - - /* get list of valid positions */ - QList validpos; - for (unsigned int x = 0; x < Constants::map_size.width; ++x) - { - for (unsigned int y = 0; y < Constants::map_size.height; ++y) - { - if (visualMap[x][y] == NULL) - validpos.append(QPoint(x, y)); - } - } - - /* remove actors positions from list - * performance would be better if actors would be listed in visualMap too - * but this isn't possible that easily. see comment in updateMap(map) - */ - foreach (Actor *actor, m_actors) - { - QPoint actorpos = CoordToMapPosition(actor->pos().toPoint()); - validpos.removeAll(actorpos); - } - - if (validpos.empty()) - return QPoint(); - - rand = (int) (validpos.size() * (qrand() / (RAND_MAX + 1.0))); - QPoint pos = validpos.at(rand); - map[pos.x()][pos.y()] = type; - return pos; -} - -void Server::colorizeBlocks(Transmission::map_t map) -{ - /* decrement tickcount of colored blocks */ - if (!m_coloredBlocks.empty()) - { - QMutableMapIterator i(m_coloredBlocks); - while(i.hasNext()) - { - i.next(); - unsigned val = i.value(); - if (val > 0) - i.setValue(--val); - else - { - QPoint block = i.key(); - /* check for actor collision */ - bool skip = false; - foreach (Actor *actor, m_actors) - { - if (CoordToMapPosition(actor->pos().toPoint()) == block) - skip = true; - if (skip) - break; - } - if (skip) - continue; - - map[block.x()][block.y()] |= Transmission::block | Color::none; - updateMap(map, block.x(), block.y()); - m_blocks.append(block); - i.remove(); - } - } - } - - /* colorize a random block */ - int rand = (int) (Constants::Game::colorize_block_chance * (qrand() / (RAND_MAX + 1.0))); - if (rand == 0) - { - rand = (int) (m_blocks.size() * (qrand() / (RAND_MAX + 1.0))); - QPoint block = m_blocks.at(rand); - m_blocks.removeAt(rand); - - unsigned int min = Constants::Game::colorize_block_tickcount_min; - unsigned int max = Constants::Game::colorize_block_tickcount_max; - int tickcount = min + (int) ((max - min + 1) * (qrand() / (RAND_MAX + 1.0))); - m_coloredBlocks.insert(block, tickcount); - - unsigned int color = (int) (m_maxplayers * (qrand() / (RAND_MAX + 1.0))); - map[block.x()][block.y()] |= Transmission::block | Color::order[color]; - updateMap(map, block.x(), block.y()); - } -} - -bool Server::waitForClientConnections() -{ - // server must stay alive as long as sockets (qt parent mem mechanism) - QTcpServer *tcpSrv = new QTcpServer(this); - tcpSrv->listen(m_bindaddress, m_port); - if (!tcpSrv->isListening()) - { - qCritical() << "Error while creating socket:" << qPrintable(tcpSrv->errorString()); - return false; - } - std::cout << "[Server] Listening on: " - << qPrintable(QString("%1:%2").arg(tcpSrv->serverAddress().toString()) - .arg(tcpSrv->serverPort())) << std::endl; - - std::cout << "[Server] Waiting for clients" << std::endl; - ProtoBuf::Init packet; - packet.set_maxplayers(m_maxplayers); - for (unsigned int i = 0; i < (m_maxplayers - m_numbots); ++i) - { - bool connectionAvailable = tcpSrv->waitForNewConnection(-1); - Q_ASSERT(connectionAvailable); - Q_UNUSED(connectionAvailable); - QTcpSocket *socket = tcpSrv->nextPendingConnection(); - connect(socket, SIGNAL(readyRead()), this, SLOT(keyPressUpdate())); - - /* assign color and notify client */ - Color::Color color = Color::order[i]; - m_clientConnections[color] = socket; - packet.set_color(color); - Util::sendPacket(packet, socket); - std::cout << "[Connect] New Player: color=" << qPrintable(Util::colorToString(color)) << std::endl; - } - - for (unsigned int i = (m_maxplayers - m_numbots); i < m_maxplayers; ++i) - { - m_bots.append(Color::order[i]); - m_actorMovements[Color::order[i]] = Actor::None; - } - - qDebug() << "[Server] All Clients connected"; - return true; -} - -void Server::sendUpdate(Transmission::map_t map, bool firstPacket) -{ - m_updatepacket.Clear(); - - for (unsigned int x = 0; x < Constants::map_size.width; ++x) - { - for (unsigned int y = 0; y < Constants::map_size.height; ++y) - m_updatepacket.add_field(map[x][y]); - } - - for(unsigned int i = 0; i < m_maxplayers; ++i) - { - m_updatepacket.add_round_points(m_actors.value(Color::order[i])->getRoundPoints()); - m_updatepacket.add_game_points(m_actors.value(Color::order[i])->getGamePoints()); - } - - /* we send the eating_order inside the first packet */ - if (firstPacket) - { - foreach(Color::Color color, m_eatingorder) - m_updatepacket.add_eating_order(color); - } - - QSharedPointer data = Util::createPacket(m_updatepacket); - QMutableMapIterator i(m_clientConnections); - while(i.hasNext()) - { - i.next(); - QTcpSocket *socket = i.value(); - - if (!Util::sendPacket(data.data(), socket)) - { - qWarning() << "[Connect] Error while sending data to client" << i.key() << "-> Disconnecting..."; - socket->close(); - std::cout << "[Connect] Actor color=" << qPrintable(Util::colorToString(i.key())) - << " is now a bot" << std::endl; - m_bots.append(i.key()); - ++m_numbots; - i.remove(); - } - } - - if (m_maxplayers == m_numbots) - { - std::cout << "[Connect] No more real players left. Exiting..." << std::endl; - qApp->quit(); - } -} - -void Server::botCalculate(Actor *actor) -{ - QPoint actorpos = CoordToMapPosition(actor->pos().toPoint()); - - /* first make list of possible directions based on current actor position */ - QHash directions; - if (actorpos.x() > 0) - directions.insert(Actor::Left, 0); - if (actorpos.x() < visualMap.size() - 1) - directions.insert(Actor::Right, 0); - if (actorpos.y() > 0) - directions.insert(Actor::Up, 0); - if (actorpos.y() < visualMap[actorpos.x()].size() - 1) - directions.insert(Actor::Down, 0); - - /* check neighbours for blocks first */ - QMutableHashIterator i(directions); - while(i.hasNext()) - { - i.next(); - QPoint newpos = actorpos + Actor::movementToPoint(i.key()); - if (newpos.x() < 0 || newpos.x() >= visualMap.size()) - continue; - if (newpos.y() < 0 || newpos.y() >= visualMap[newpos.x()].size()) - continue; - GameEntity *item = visualMap[newpos.x()][newpos.y()]; - - /* check if neighbour is a block */ - Block *block = qgraphicsitem_cast(item); - if (block != NULL && block->color() != actor->color()) - i.remove(); - } - - /* we're enclosed by blocks */ - if (directions.empty()) - return; - - /* determine if other actors are in range to be afraid/to hunt */ - int mindistance = Constants::AI::player_minimum_distance; - QList pos_afraid; - QList pos_hunt; - foreach (Actor *other, m_actors) - { - if (actor == other) - continue; - - QList *ptr = NULL; - if (other->canEat(actor, m_eatingorder)) - ptr = &pos_afraid; - else if (actor->canEat(other, m_eatingorder)) - ptr = &pos_hunt; - if (ptr == NULL) - continue; - - QPoint otherpos = CoordToMapPosition(other->pos().toPoint()); - QPoint distance = actorpos - otherpos; - if (distance.manhattanLength() < mindistance) - ptr->append(otherpos); - } - - /* check new directions and change direction-weight */ - i = directions; - while(i.hasNext()) - { - i.next(); - QPoint newpos = actorpos + Actor::movementToPoint(i.key()); - - /* check for new positions in afraid list */ - foreach(QPoint otherpos, pos_afraid) - { - int olddistance = (actorpos - otherpos).manhattanLength(); - int newdistance = (newpos - otherpos).manhattanLength(); - if (newdistance >= olddistance) - i.setValue(i.value() + Constants::AI::weight_afraid); - - /* check for blocks of own color: other pacman can't follow their */ - GameEntity *item = visualMap[newpos.x()][newpos.y()]; - Block *block = qgraphicsitem_cast(item); - if (block != NULL && block->color() == actor->color()) - i.setValue(i.value() + Constants::AI::weight_colorblock); - } - - /* check for new positions in hunt list */ - foreach(QPoint otherpos, pos_hunt) - { - int olddistance = (actorpos - otherpos).manhattanLength(); - int newdistance = (newpos - otherpos).manhattanLength(); - if (newdistance <= olddistance) - i.setValue(i.value() + Constants::AI::weight_hunt); - } - - /* check for bonuspoint */ - GameEntity *item = visualMap[newpos.x()][newpos.y()]; - BonusPoint *bpoint = qgraphicsitem_cast(item); - if (bpoint != NULL) - i.setValue(i.value() + Constants::AI::weight_bonus_point); - - /* check for normal point */ - Point *point = qgraphicsitem_cast(item); - if (point != NULL) - i.setValue(i.value() + Constants::AI::weight_point); - } - - /* sort directions */ - QList weightlist = directions.values(); - qSort(weightlist.begin(), weightlist.end(), qGreater()); - - /* remove directions with lesser weight */ - unsigned int max = weightlist.at(0); - i = directions; - while(i.hasNext()) - { - i.next(); - if (i.value() < max) - i.remove(); - } - - QList list = directions.keys(); - - /* default is no direction change */ - if (list.contains(actor->direction())) - return; - - /* random direction */ - int rand = (int) (list.size() * (qrand() / (RAND_MAX + 1.0))); - m_actorMovements[actor->color()] = list.at(rand); -} - -void Server::keyPressUpdate() -{ - ProtoBuf::KeyPressUpdate packet; - QMapIterator i(m_clientConnections); - while (i.hasNext()) - { - i.next(); - Color::Color color = i.key(); - QTcpSocket *socket = i.value(); - QDataStream in(i.value()); - while (socket->bytesAvailable() > (qint64)sizeof(qint64)) - { - QSharedPointer data = Util::receivePacket(socket); - bool worked = packet.ParseFromArray(data->data(), data->size()); - Q_ASSERT(worked); - Q_UNUSED(worked); - Transmission::field_t direction = packet.newkey(); - qDebug() << "[KeyPress] actor=" << color << "direction=" << direction; - m_actorMovements[color] = Util::transmissionMovementToActor(direction); - } - } -} - -void Server::initRoundMap() -{ - std::cout << "[Game] New round starts..." << std::endl; - m_tickTimer->stop(); - - /* reset scene and clean up items */ - reset(); - - /* randomize color eating order */ - m_eatingorder.removeLast(); - random_shuffle(m_eatingorder.begin(), m_eatingorder.end()); - m_eatingorder.append(m_eatingorder.at(0)); - - /* create new map */ - Transmission::map_t map = Util::createDemoMap(); - Util::placeActors(map, m_maxplayers, Color::order); - Util::fillPoints(map); - -#if 0 // actor eating actor tests - TODO: remove - m_actorMovements.clear(); -#if 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][1] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); -#elif 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][3] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); -#elif 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][4] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); -#elif 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][5] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); -#elif 0 - //works - map[0][0] = Color::order[1] | Transmission::pacman; - map[0][5] = Color::order[0] | Transmission::pacman; - m_actorMovements.insert(Color::order[1], Actor::Down); -#elif 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][5] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); - m_actorMovements.insert(Color::order[1], Actor::Up); -#elif 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][6] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); - m_actorMovements.insert(Color::order[1], Actor::Up); -#elif 0 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][7] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); - m_actorMovements.insert(Color::order[1], Actor::Up); -#elif 1 - //works - map[0][0] = Color::order[0] | Transmission::pacman; - map[0][1] = Color::order[1] | Transmission::pacman; - m_actorMovements.insert(Color::order[0], Actor::Down); - m_actorMovements.insert(Color::order[1], Actor::Down); -#endif -#endif - - /* save positions of blocks for later usage */ - m_blocks.clear(); - for (unsigned int x = 0; x < Constants::map_size.width; ++x) - { - for (unsigned int y = 0; y < Constants::map_size.height; ++y) - { - Transmission::field_t &cur = map[x][y]; - if (cur & Transmission::block) - m_blocks.append(QPoint(x, y)); - } - } - - updateMap(map); - sendUpdate(map, true); - Util::deleteMap(map); - map = NULL; - - m_actorMovements.clear(); - - disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); - connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame())); - AudioManager::self()->play(Sound::Intro, true); - m_tickTimer->start(); -} - -void Server::startGame() -{ - m_running = true; -} - -void Server::stopGame(bool delay) -{ - /* first finish previous round */ - foreach(Actor *actor, m_actors) - actor->finishRound(); - m_finishRound = false; - m_running = false; - - /* add delay if requested */ - if (delay) - { - disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); - connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame())); - AudioManager::self()->play(Sound::Die, true); - return; - } - - std::cout << "[Game] Round finished..." << std::endl; - - /* do next-round work */ - ++m_curRound; - if(m_rounds == 0 || m_curRound < m_rounds) - initRoundMap(); - else - { - /* end of game */ - std::cout << "[Game] All round finished. Exiting..." << std::endl; - qApp->quit(); - } -} - -void Server::setFinishRound() -{ - m_finishRound = true; -} - -bool Server::parseCommandline() -{ - AnyOption opt; - opt.setVerbose(); - - /* usage strings must remain valid until parsing is done */ - QString exec = QFileInfo(qApp->applicationFilePath()).fileName(); - QByteArray usage; - QTextStream out(&usage, QIODevice::ReadWrite | QIODevice::Text); - out << "Usage: " << exec << " [OPTION]" << endl - << "Usage: " << exec << " -h" << endl - << endl; - out << " -b, --bind " << endl - << " Specifies the ip address on which the server listens for connections" << endl - << " Default: " << m_bindaddress.toString() << endl - << endl; - opt.setOption("bind", 'b'); - out << " -p, --port " << endl - << " Specifies the port on which the server listens for connections" << endl - << " Default: " << m_port << endl - << endl; - opt.setOption("port", 'p'); - out << " -m, --maxplayers [1.." << m_maxplayers << "]" << endl - << " Specifies the maximum number of players/pacmans" << endl - << " Default: " << m_maxplayers << endl - << endl; - opt.setOption("maxplayers", 'm'); - out << " --bots [0..maxplayers-1]" << endl - << " Specifies the number of AI pacmans/bots" << endl - << " Default: " << m_numbots << endl - << endl; - opt.setOption("bots"); - out << " --nocolorblocks" << endl - << " Disable random colorized blocks" << endl - << endl; - opt.setOption("rounds", 'r'); - out << " -r, --rounds [0 | 1..n]" << endl - << " Number of rounds to play" << endl - << " Default: " << m_rounds << endl - << endl; - opt.setFlag("nocolorblocks"); - out << " -h, --help" << endl - << " Prints this help message" << endl; - opt.setFlag("help", 'h'); - out.flush(); - opt.addUsage(usage.constData()); - opt.processCommandArgs(qApp->argc(), qApp->argv()); - - if (opt.getFlag("help") || opt.getFlag('h')) - { - opt.printUsage(); - return false; - } - - if (opt.getValue("port") != NULL) - { - bool ok; - m_port = QString(opt.getValue("port")).toUInt(&ok); - if (!ok || m_port < 1 || m_port > 65535) - { - qCritical() << "Invalid port-option:" << opt.getValue("port") << endl - << "Port must be between 1 and 65535"; - return false; - } - } - - if (opt.getValue("bind") != NULL) - { - m_bindaddress = opt.getValue("bind"); - if (m_bindaddress.isNull()) - { - qCritical() << "Invalid bind-option:" << opt.getValue("bind") << endl - << "Bind address must be an ip address"; - return false; - } - } - - if (opt.getValue("maxplayers") != NULL) - { - bool ok; - unsigned int maxplayers = QString(opt.getValue("maxplayers")).toUInt(&ok); - if (!ok || maxplayers < 1 || maxplayers > m_maxplayers) - { - qCritical() << "Invalid maxplayers-option:" << opt.getValue("maxplayers") << endl - << "Maxplayers must be between 1 and" << m_maxplayers; - return false; - } - m_maxplayers = maxplayers; - if (m_maxplayers == 2) - { - qCritical() << "2 player game is not supported (who wins if a player gets eaten?)"; - return false; - } - } - - if (opt.getValue("bots") != NULL) - { - bool ok; - unsigned int numbots = QString(opt.getValue("bots")).toUInt(&ok); - if (!ok || numbots >= m_maxplayers) - { - qCritical() << "Invalid numbots-options:" << opt.getValue("bots") << endl - << "AI pacmans/bots must be between 0 and" << m_maxplayers - 1; - return false; - } - m_numbots = numbots; - } - - if (opt.getValue("rounds") != NULL) - { - bool ok; - unsigned int rounds = QString(opt.getValue("rounds")).toUInt(&ok); - if (!ok) - { - qCritical() << "Invalid number of rounds: " << opt.getValue("rounds") << endl; - return false; - } - m_rounds = rounds; - } - - this->setProperty("coloredblocks", !opt.getFlag("nocolorblocks")); - - return true; -} - -bool operator<(const QPoint& lhs, const QPoint& rhs) -{ - if (lhs.x() < rhs.x()) - return true; - else if (lhs.x() == rhs.x()) - return lhs.y() < rhs.y(); - else - return false; -} - -bool Constants::server = true; - -int main(int argc, char **argv) -{ - /* Verify that the version of the library that we linked against is - * compatible with the version of the headers we compiled against. - */ - GOOGLE_PROTOBUF_VERIFY_VERSION; - - QApplication app(argc, argv, false); - app.setApplicationName("Pacman Server"); - app.setWindowIcon(QIcon(":/appicon")); - - qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); - - int ret = 0; - Server server; - if (!ret && !server.parseCommandline()) - ret = 1; - if (!ret && !server.run()) - ret = 1; - if (!ret) - ret = app.exec(); - - /* Delete all global objects allocated by libprotobuf */ - google::protobuf::ShutdownProtobufLibrary(); - - return ret; -} -- cgit v1.2.3