From 85b09864f6d489e8c998e9f172d25079d572c602 Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 18 Apr 2011 19:47:34 +0200 Subject: - add actor.canEat(other) to check if actor can eat other (note: that doesn't mean that other can eat actor!!) - server now generated and sends the colorlist to the server in the first map update packet - add a better AI --- pacman-c++/server.cpp | 145 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 117 insertions(+), 28 deletions(-) (limited to 'pacman-c++/server.cpp') diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp index 65a8f8b..4219a43 100644 --- a/pacman-c++/server.cpp +++ b/pacman-c++/server.cpp @@ -19,6 +19,11 @@ Server::Server(QWidget *parent) bool Server::run() { + /* create eating order list first - this can also be created dynamically per round (theoretically) */ + for(unsigned i = 0; i < m_maxplayers; ++i) + m_eatingorder.append(Color::order[i]); + m_eatingorder.append(Color::order[0]); + qDebug() << "[Server] Running server..."; qDebug() << "[Server] Max players:" << m_maxplayers; qDebug() << "[Server] Number of bots:" << m_numbots; @@ -42,7 +47,7 @@ bool Server::run() } updateMap(map); - sendUpdate(map); + sendUpdate(map, true); Util::deleteMap(map); map = NULL; @@ -55,7 +60,7 @@ bool Server::run() void Server::tick() { //qDebug() << "[Tick] Doing server update"; - foreach(Color::Color color, m_bots) + foreach (Color::Color color, m_bots) botCalculate(m_actors[color]); Transmission::map_t map = calculateUpdates(); updateMap(map); @@ -218,7 +223,7 @@ void Server::colorizeBlocks(Transmission::map_t map) { /* check for actor collision */ bool skip = false; - foreach(Actor *actor, m_actors) + foreach (Actor *actor, m_actors) { if (CoordToMapPosition(actor->pos().toPoint()) == i.key()) skip = true; @@ -272,6 +277,7 @@ bool Server::waitForClientConnections() qDebug() << "[Server] Waiting for clients"; ProtoBuf::Init packet; + packet.set_maxplayers(m_maxplayers); for (unsigned int i = 0; i < (m_maxplayers - m_numbots); ++i) { bool connectionAvailable = tcpSrv->waitForNewConnection(-1); @@ -284,7 +290,6 @@ bool Server::waitForClientConnections() Color::Color color = Color::order[i]; m_clientConnections[color] = socket; packet.set_color(color); - packet.set_maxplayers(m_maxplayers); Util::sendPacket(packet, socket); qDebug() << "[Connect] New Player: color=" << color; } @@ -299,7 +304,7 @@ bool Server::waitForClientConnections() return true; } -void Server::sendUpdate(Transmission::map_t map) +void Server::sendUpdate(Transmission::map_t map, bool firstPacket) { m_updatepacket.Clear(); @@ -315,6 +320,13 @@ void Server::sendUpdate(Transmission::map_t map) 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()) @@ -349,53 +361,125 @@ void Server::botCalculate(Actor *actor) QPoint actorpos = CoordToMapPosition(actor->pos().toPoint()); /* first make list of possible directions based on current actor position */ - QList directions; + QHash directions; if (actorpos.x() > 0) - directions.append(Actor::Left); + directions.insert(Actor::Left, 0); if (actorpos.x() < visualMap.size() - 1) - directions.append(Actor::Right); + directions.insert(Actor::Right, 0); if (actorpos.y() > 0) - directions.append(Actor::Up); + directions.insert(Actor::Up, 0); if (actorpos.y() < visualMap[actorpos.x()].size() - 1) - directions.append(Actor::Down); + directions.insert(Actor::Down, 0); - /* copy of directions: used if there's no good direction based on rules */ - QList directions2(directions); - - QMutableListIterator i(directions); + /* check neighbours for blocks first */ + QMutableHashIterator i(directions); while(i.hasNext()) { i.next(); - Actor::Movement direction = i.value(); - QPoint pos = actorpos + Actor::movementToPoint(direction); - if (pos.x() < 0 || pos.x() >= visualMap.size()) + QPoint newpos = actorpos + Actor::movementToPoint(i.key()); + if (newpos.x() < 0 || newpos.x() >= visualMap.size()) continue; - if (pos.y() < 0 || pos.y() >= visualMap[pos.x()].size()) + if (newpos.y() < 0 || newpos.y() >= visualMap[newpos.x()].size()) continue; - GameEntity *item = visualMap[pos.x()][pos.y()]; + 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(); - directions2.removeAll(direction); continue; } + } + + /* we're enclosed by blocks */ + if (directions.empty()) + return; + + /* determine if other actors are in range to afraid/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); + } - /* if neighbour is not a point */ + /* 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 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 (bpoint == NULL && point == NULL) - { + 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(); - continue; - } } - QList *ptr = (!directions.empty()) ? &directions : &directions2; - int rand = (int) (ptr->size() * (qrand() / (RAND_MAX + 1.0))); - m_actorMovements[actor->color()] = ptr->at(rand); + 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() @@ -504,6 +588,11 @@ bool Server::parseCommandline() 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) -- cgit v1.2.3