diff options
| author | manuel <manuel@mausz.at> | 2011-04-18 19:47:34 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2011-04-18 19:47:34 +0200 |
| commit | 85b09864f6d489e8c998e9f172d25079d572c602 (patch) | |
| tree | a6e38da5dc828810b21045d0ac1e4babcf198825 /pacman-c++/server.cpp | |
| parent | e373442901064d07791c9739daa380acb1dfbb8c (diff) | |
| download | foop-85b09864f6d489e8c998e9f172d25079d572c602.tar.gz foop-85b09864f6d489e8c998e9f172d25079d572c602.tar.bz2 foop-85b09864f6d489e8c998e9f172d25079d572c602.zip | |
- 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
Diffstat (limited to 'pacman-c++/server.cpp')
| -rw-r--r-- | pacman-c++/server.cpp | 145 |
1 files changed, 117 insertions, 28 deletions
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) | |||
| 19 | 19 | ||
| 20 | bool Server::run() | 20 | bool Server::run() |
| 21 | { | 21 | { |
| 22 | /* create eating order list first - this can also be created dynamically per round (theoretically) */ | ||
| 23 | for(unsigned i = 0; i < m_maxplayers; ++i) | ||
| 24 | m_eatingorder.append(Color::order[i]); | ||
| 25 | m_eatingorder.append(Color::order[0]); | ||
| 26 | |||
| 22 | qDebug() << "[Server] Running server..."; | 27 | qDebug() << "[Server] Running server..."; |
| 23 | qDebug() << "[Server] Max players:" << m_maxplayers; | 28 | qDebug() << "[Server] Max players:" << m_maxplayers; |
| 24 | qDebug() << "[Server] Number of bots:" << m_numbots; | 29 | qDebug() << "[Server] Number of bots:" << m_numbots; |
| @@ -42,7 +47,7 @@ bool Server::run() | |||
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | updateMap(map); | 49 | updateMap(map); |
| 45 | sendUpdate(map); | 50 | sendUpdate(map, true); |
| 46 | Util::deleteMap(map); | 51 | Util::deleteMap(map); |
| 47 | map = NULL; | 52 | map = NULL; |
| 48 | 53 | ||
| @@ -55,7 +60,7 @@ bool Server::run() | |||
| 55 | void Server::tick() | 60 | void Server::tick() |
| 56 | { | 61 | { |
| 57 | //qDebug() << "[Tick] Doing server update"; | 62 | //qDebug() << "[Tick] Doing server update"; |
| 58 | foreach(Color::Color color, m_bots) | 63 | foreach (Color::Color color, m_bots) |
| 59 | botCalculate(m_actors[color]); | 64 | botCalculate(m_actors[color]); |
| 60 | Transmission::map_t map = calculateUpdates(); | 65 | Transmission::map_t map = calculateUpdates(); |
| 61 | updateMap(map); | 66 | updateMap(map); |
| @@ -218,7 +223,7 @@ void Server::colorizeBlocks(Transmission::map_t map) | |||
| 218 | { | 223 | { |
| 219 | /* check for actor collision */ | 224 | /* check for actor collision */ |
| 220 | bool skip = false; | 225 | bool skip = false; |
| 221 | foreach(Actor *actor, m_actors) | 226 | foreach (Actor *actor, m_actors) |
| 222 | { | 227 | { |
| 223 | if (CoordToMapPosition(actor->pos().toPoint()) == i.key()) | 228 | if (CoordToMapPosition(actor->pos().toPoint()) == i.key()) |
| 224 | skip = true; | 229 | skip = true; |
| @@ -272,6 +277,7 @@ bool Server::waitForClientConnections() | |||
| 272 | 277 | ||
| 273 | qDebug() << "[Server] Waiting for clients"; | 278 | qDebug() << "[Server] Waiting for clients"; |
| 274 | ProtoBuf::Init packet; | 279 | ProtoBuf::Init packet; |
| 280 | packet.set_maxplayers(m_maxplayers); | ||
| 275 | for (unsigned int i = 0; i < (m_maxplayers - m_numbots); ++i) | 281 | for (unsigned int i = 0; i < (m_maxplayers - m_numbots); ++i) |
| 276 | { | 282 | { |
| 277 | bool connectionAvailable = tcpSrv->waitForNewConnection(-1); | 283 | bool connectionAvailable = tcpSrv->waitForNewConnection(-1); |
| @@ -284,7 +290,6 @@ bool Server::waitForClientConnections() | |||
| 284 | Color::Color color = Color::order[i]; | 290 | Color::Color color = Color::order[i]; |
| 285 | m_clientConnections[color] = socket; | 291 | m_clientConnections[color] = socket; |
| 286 | packet.set_color(color); | 292 | packet.set_color(color); |
| 287 | packet.set_maxplayers(m_maxplayers); | ||
| 288 | Util::sendPacket(packet, socket); | 293 | Util::sendPacket(packet, socket); |
| 289 | qDebug() << "[Connect] New Player: color=" << color; | 294 | qDebug() << "[Connect] New Player: color=" << color; |
| 290 | } | 295 | } |
| @@ -299,7 +304,7 @@ bool Server::waitForClientConnections() | |||
| 299 | return true; | 304 | return true; |
| 300 | } | 305 | } |
| 301 | 306 | ||
| 302 | void Server::sendUpdate(Transmission::map_t map) | 307 | void Server::sendUpdate(Transmission::map_t map, bool firstPacket) |
| 303 | { | 308 | { |
| 304 | m_updatepacket.Clear(); | 309 | m_updatepacket.Clear(); |
| 305 | 310 | ||
| @@ -315,6 +320,13 @@ void Server::sendUpdate(Transmission::map_t map) | |||
| 315 | m_updatepacket.add_game_points(m_actors.value(Color::order[i])->getGamePoints()); | 320 | m_updatepacket.add_game_points(m_actors.value(Color::order[i])->getGamePoints()); |
| 316 | } | 321 | } |
| 317 | 322 | ||
| 323 | /* we send the eating_order inside the first packet */ | ||
| 324 | if (firstPacket) | ||
| 325 | { | ||
| 326 | foreach(Color::Color color, m_eatingorder) | ||
| 327 | m_updatepacket.add_eating_order(color); | ||
| 328 | } | ||
| 329 | |||
| 318 | QSharedPointer<QByteArray> data = Util::createPacket(m_updatepacket); | 330 | QSharedPointer<QByteArray> data = Util::createPacket(m_updatepacket); |
| 319 | QMutableMapIterator<Color::Color, QTcpSocket *> i(m_clientConnections); | 331 | QMutableMapIterator<Color::Color, QTcpSocket *> i(m_clientConnections); |
| 320 | while(i.hasNext()) | 332 | while(i.hasNext()) |
| @@ -349,53 +361,125 @@ void Server::botCalculate(Actor *actor) | |||
| 349 | QPoint actorpos = CoordToMapPosition(actor->pos().toPoint()); | 361 | QPoint actorpos = CoordToMapPosition(actor->pos().toPoint()); |
| 350 | 362 | ||
| 351 | /* first make list of possible directions based on current actor position */ | 363 | /* first make list of possible directions based on current actor position */ |
| 352 | QList<Actor::Movement> directions; | 364 | QHash<Actor::Movement, unsigned int> directions; |
| 353 | if (actorpos.x() > 0) | 365 | if (actorpos.x() > 0) |
| 354 | directions.append(Actor::Left); | 366 | directions.insert(Actor::Left, 0); |
| 355 | if (actorpos.x() < visualMap.size() - 1) | 367 | if (actorpos.x() < visualMap.size() - 1) |
| 356 | directions.append(Actor::Right); | 368 | directions.insert(Actor::Right, 0); |
| 357 | if (actorpos.y() > 0) | 369 | if (actorpos.y() > 0) |
| 358 | directions.append(Actor::Up); | 370 | directions.insert(Actor::Up, 0); |
| 359 | if (actorpos.y() < visualMap[actorpos.x()].size() - 1) | 371 | if (actorpos.y() < visualMap[actorpos.x()].size() - 1) |
| 360 | directions.append(Actor::Down); | 372 | directions.insert(Actor::Down, 0); |
| 361 | 373 | ||
| 362 | /* copy of directions: used if there's no good direction based on rules */ | 374 | /* check neighbours for blocks first */ |
| 363 | QList<Actor::Movement> directions2(directions); | 375 | QMutableHashIterator<Actor::Movement, unsigned int> i(directions); |
| 364 | |||
| 365 | QMutableListIterator<Actor::Movement> i(directions); | ||
| 366 | while(i.hasNext()) | 376 | while(i.hasNext()) |
| 367 | { | 377 | { |
| 368 | i.next(); | 378 | i.next(); |
| 369 | Actor::Movement direction = i.value(); | 379 | QPoint newpos = actorpos + Actor::movementToPoint(i.key()); |
| 370 | QPoint pos = actorpos + Actor::movementToPoint(direction); | 380 | if (newpos.x() < 0 || newpos.x() >= visualMap.size()) |
| 371 | if (pos.x() < 0 || pos.x() >= visualMap.size()) | ||
| 372 | continue; | 381 | continue; |
| 373 | if (pos.y() < 0 || pos.y() >= visualMap[pos.x()].size()) | 382 | if (newpos.y() < 0 || newpos.y() >= visualMap[newpos.x()].size()) |
| 374 | continue; | 383 | continue; |
| 375 | GameEntity *item = visualMap[pos.x()][pos.y()]; | 384 | GameEntity *item = visualMap[newpos.x()][newpos.y()]; |
| 376 | 385 | ||
| 377 | /* check if neighbour is a block */ | 386 | /* check if neighbour is a block */ |
| 378 | Block *block = qgraphicsitem_cast<Block *>(item); | 387 | Block *block = qgraphicsitem_cast<Block *>(item); |
| 379 | if (block != NULL && block->color() != actor->color()) | 388 | if (block != NULL && block->color() != actor->color()) |
| 380 | { | 389 | { |
| 381 | i.remove(); | 390 | i.remove(); |
| 382 | directions2.removeAll(direction); | ||
| 383 | continue; | 391 | continue; |
| 384 | } | 392 | } |
| 393 | } | ||
| 394 | |||
| 395 | /* we're enclosed by blocks */ | ||
| 396 | if (directions.empty()) | ||
| 397 | return; | ||
| 398 | |||
| 399 | /* determine if other actors are in range to afraid/hunt*/ | ||
| 400 | int mindistance = Constants::AI::player_minimum_distance; | ||
| 401 | QList<QPoint> pos_afraid; | ||
| 402 | QList<QPoint> pos_hunt; | ||
| 403 | foreach (Actor *other, m_actors) | ||
| 404 | { | ||
| 405 | if (actor == other) | ||
| 406 | continue; | ||
| 407 | |||
| 408 | QList<QPoint> *ptr = NULL; | ||
| 409 | if (other->canEat(actor, m_eatingorder)) | ||
| 410 | ptr = &pos_afraid; | ||
| 411 | else if (actor->canEat(other, m_eatingorder)) | ||
| 412 | ptr = &pos_hunt; | ||
| 413 | if (ptr == NULL) | ||
| 414 | continue; | ||
| 415 | |||
| 416 | QPoint otherpos = CoordToMapPosition(other->pos().toPoint()); | ||
| 417 | QPoint distance = actorpos - otherpos; | ||
| 418 | if (distance.manhattanLength() < mindistance) | ||
| 419 | ptr->append(otherpos); | ||
| 420 | } | ||
| 385 | 421 | ||
| 386 | /* if neighbour is not a point */ | 422 | /* check new directions and change direction-weight */ |
| 423 | i = directions; | ||
| 424 | while(i.hasNext()) | ||
| 425 | { | ||
| 426 | i.next(); | ||
| 427 | QPoint newpos = actorpos + Actor::movementToPoint(i.key()); | ||
| 428 | |||
| 429 | /* check for new positions in afraid list */ | ||
| 430 | foreach(QPoint otherpos, pos_afraid) | ||
| 431 | { | ||
| 432 | int olddistance = (actorpos - otherpos).manhattanLength(); | ||
| 433 | int newdistance = (newpos - otherpos).manhattanLength(); | ||
| 434 | if (newdistance >= olddistance) | ||
| 435 | i.setValue(i.value() += Constants::AI::weight_afraid); | ||
| 436 | } | ||
| 437 | |||
| 438 | /* check for new positions in hunt list */ | ||
| 439 | foreach(QPoint otherpos, pos_hunt) | ||
| 440 | { | ||
| 441 | int olddistance = (actorpos - otherpos).manhattanLength(); | ||
| 442 | |||
| 443 | int newdistance = (newpos - otherpos).manhattanLength(); | ||
| 444 | if (newdistance <= olddistance) | ||
| 445 | i.setValue(i.value() += Constants::AI::weight_hunt); | ||
| 446 | } | ||
| 447 | |||
| 448 | /* check for bonuspoint */ | ||
| 449 | GameEntity *item = visualMap[newpos.x()][newpos.y()]; | ||
| 387 | BonusPoint *bpoint = qgraphicsitem_cast<BonusPoint *>(item); | 450 | BonusPoint *bpoint = qgraphicsitem_cast<BonusPoint *>(item); |
| 451 | if (bpoint != NULL) | ||
| 452 | i.setValue(i.value() + Constants::AI::weight_bonus_point); | ||
| 453 | |||
| 454 | /* check for normal point */ | ||
| 388 | Point *point = qgraphicsitem_cast<Point *>(item); | 455 | Point *point = qgraphicsitem_cast<Point *>(item); |
| 389 | if (bpoint == NULL && point == NULL) | 456 | if (point != NULL) |
| 390 | { | 457 | i.setValue(i.value() + Constants::AI::weight_point); |
| 458 | } | ||
| 459 | |||
| 460 | /* sort directions */ | ||
| 461 | QList<unsigned int> weightlist = directions.values(); | ||
| 462 | qSort(weightlist.begin(), weightlist.end(), qGreater<unsigned int>()); | ||
| 463 | |||
| 464 | /* remove directions with lesser weight */ | ||
| 465 | unsigned int max = weightlist.at(0); | ||
| 466 | i = directions; | ||
| 467 | while(i.hasNext()) | ||
| 468 | { | ||
| 469 | i.next(); | ||
| 470 | if (i.value() < max) | ||
| 391 | i.remove(); | 471 | i.remove(); |
| 392 | continue; | ||
| 393 | } | ||
| 394 | } | 472 | } |
| 395 | 473 | ||
| 396 | QList<Actor::Movement> *ptr = (!directions.empty()) ? &directions : &directions2; | 474 | QList<Actor::Movement> list = directions.keys(); |
| 397 | int rand = (int) (ptr->size() * (qrand() / (RAND_MAX + 1.0))); | 475 | |
| 398 | m_actorMovements[actor->color()] = ptr->at(rand); | 476 | /* default is no direction change */ |
| 477 | if (list.contains(actor->direction())) | ||
| 478 | return; | ||
| 479 | |||
| 480 | /* random direction */ | ||
| 481 | int rand = (int) (list.size() * (qrand() / (RAND_MAX + 1.0))); | ||
| 482 | m_actorMovements[actor->color()] = list.at(rand); | ||
| 399 | } | 483 | } |
| 400 | 484 | ||
| 401 | void Server::keyPressUpdate() | 485 | void Server::keyPressUpdate() |
| @@ -504,6 +588,11 @@ bool Server::parseCommandline() | |||
| 504 | return false; | 588 | return false; |
| 505 | } | 589 | } |
| 506 | m_maxplayers = maxplayers; | 590 | m_maxplayers = maxplayers; |
| 591 | if (m_maxplayers == 2) | ||
| 592 | { | ||
| 593 | qCritical() << "2 player game is not supported (who wins if a player gets eaten?)"; | ||
| 594 | return false; | ||
| 595 | } | ||
| 507 | } | 596 | } |
| 508 | 597 | ||
| 509 | if (opt.getValue("bots") != NULL) | 598 | if (opt.getValue("bots") != NULL) |
