File indexing completed on 2025-03-09 03:49:43

0001 /*
0002     SPDX-FileCopyrightText: 1998 Anders Widell <d95-awi@nada.kth.se>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "PathFinder.h"
0008 
0009 #include "LevelMap.h"
0010 #include "Move.h"
0011 #include "Queue.h"
0012 
0013 //#include <cstdio>
0014 
0015 static constexpr int PATH_WALL = 32767;
0016 
0017 void PathFinder::BFS(int _x, int _y)
0018 {
0019     Queue<int, 10> xq;
0020     Queue<int, 10> yq;
0021     Queue<int, 10> dq;
0022     int x, y, d;
0023 
0024     xq.enqueue(_x);
0025     yq.enqueue(_y);
0026     dq.enqueue(1);
0027 
0028     while (!xq.empty()) {
0029         x = xq.dequeue();
0030         y = yq.dequeue();
0031         d = dq.dequeue();
0032 
0033         if (x < 0 || x > Map::MAX_X || y < 0 || y > Map::MAX_Y || dist[y][x])
0034             continue;
0035         dist[y][x] = d;
0036 
0037         xq.enqueue(x);
0038         xq.enqueue(x);
0039         xq.enqueue(x - 1);
0040         xq.enqueue(x + 1);
0041 
0042         yq.enqueue(y - 1);
0043         yq.enqueue(y + 1);
0044         yq.enqueue(y);
0045         yq.enqueue(y);
0046 
0047         dq.enqueue(d + 1);
0048         dq.enqueue(d + 1);
0049         dq.enqueue(d + 1);
0050         dq.enqueue(d + 1);
0051     }
0052 }
0053 
0054 Move *PathFinder::search(const Map *_map, int _x, int _y)
0055 {
0056     int xpos = _map->xpos();
0057     int ypos = _map->ypos();
0058     if (xpos == _x && ypos == _y)
0059         return nullptr;
0060 
0061     for (int y = 0; y <= Map::MAX_Y; y++) {
0062         for (int x = 0; x <= Map::MAX_X; x++) {
0063             if (_map->empty(x, y))
0064                 dist[y][x] = 0;
0065             else
0066                 dist[y][x] = PATH_WALL;
0067         }
0068     }
0069 
0070     BFS(_x, _y);
0071 
0072 #if 0
0073   for (int y=0; y<=Map::MAX_Y; y++) {
0074     for (int x=0; x<=Map::MAX_X; x++) {
0075       //if (x==_x && y==_y) {printf ("++ "); continue;}
0076       //if (x==xpos && y==ypos) {printf ("@@ "); continue;}
0077       if (dist[y][x] == PATH_WALL) {printf ("## "); continue;}
0078       printf ("%02d ", dist[y][x]);
0079     }
0080     printf ("\n");
0081   }
0082 #endif
0083 
0084     int d;
0085     auto *move = new Move(xpos, ypos);
0086     int oldX, oldY;
0087     for (;;) {
0088         oldX = xpos;
0089         oldY = ypos;
0090 
0091         if (xpos == _x && ypos == _y) {
0092             move->finish();
0093             // printf ("move->finish ()\n");
0094             return move;
0095         }
0096 
0097         d = dist[ypos][xpos];
0098 
0099         while (ypos - 1 >= 0 && dist[ypos - 1][xpos] < d) {
0100             ypos--;
0101             d = dist[ypos][xpos];
0102         }
0103         if (oldY != ypos) {
0104             move->step(xpos, ypos);
0105             // printf ("step (%d, %d)\n", xpos, ypos);
0106             continue;
0107         }
0108 
0109         while (ypos + 1 <= Map::MAX_Y && dist[ypos + 1][xpos] < d) {
0110             ypos++;
0111             d = dist[ypos][xpos];
0112         }
0113         if (oldY != ypos) {
0114             move->step(xpos, ypos);
0115             // printf ("step (%d, %d)\n", xpos, ypos);
0116             continue;
0117         }
0118 
0119         while (xpos - 1 >= 0 && dist[ypos][xpos - 1] < d) {
0120             xpos--;
0121             d = dist[ypos][xpos];
0122         }
0123         if (oldX != xpos) {
0124             move->step(xpos, ypos);
0125             // printf ("step (%d, %d)\n", xpos, ypos);
0126             continue;
0127         }
0128 
0129         while (xpos + 1 <= Map::MAX_X && dist[ypos][xpos + 1] < d) {
0130             xpos++;
0131             d = dist[ypos][xpos];
0132         }
0133         if (oldX != xpos) {
0134             move->step(xpos, ypos);
0135             // printf ("step (%d, %d)\n", xpos, ypos);
0136             continue;
0137         }
0138 
0139         delete move;
0140         return nullptr;
0141     }
0142 }
0143 
0144 Move *PathFinder::drag(int /* x1 */, int /* y1 */, int /* x2 */, int /* y2 */)
0145 {
0146     return nullptr;
0147 }
0148 
0149 bool PathFinder::canDrag(int /* x */, int /* y */) const
0150 {
0151     return false;
0152 }
0153 
0154 bool PathFinder::canWalkTo(int /* x */, int /* y */) const
0155 {
0156     return false;
0157 }
0158 
0159 bool PathFinder::canDragTo(int /* x */, int /* y */) const
0160 {
0161     return false;
0162 }
0163 
0164 void PathFinder::updatePossibleMoves()
0165 {
0166 }
0167 
0168 void PathFinder::updatePossibleDestinations(int /* x */, int /* y */)
0169 {
0170 }