~ubuntu-branches/ubuntu/trusty/lordsawar/trusty

« back to all changes in this revision

Viewing changes to src/path.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2008-06-17 16:07:00 UTC
  • mto: (5.1.1 lenny) (1.1.5 upstream)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20080617160700-6d8ofoz0qkasxlnw
ImportĀ upstreamĀ versionĀ 0.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
 
2
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
 
3
// Copyright (C) 2004, 2005, 2006 Andrea Paternesi
 
4
// Copyright (C) 2004 John Farrell
 
5
// Copyright (C) 2006, 2007, 2008 Ben Asselstine
 
6
// Copyright (C) 2008 Ole Laursen
 
7
//
1
8
//  This program is free software; you can redistribute it and/or modify
2
9
//  it under the terms of the GNU General Public License as published by
3
10
//  the Free Software Foundation; either version 2 of the License, or
10
17
//
11
18
//  You should have received a copy of the GNU General Public License
12
19
//  along with this program; if not, write to the Free Software
13
 
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
20
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 
21
//  02110-1301, USA.
14
22
 
15
23
#include <stdlib.h>
16
24
#include <sstream>
20
28
#include "defs.h"
21
29
#include "army.h"
22
30
#include "GameMap.h"
 
31
#include "Location.h"
23
32
#include "citylist.h"
24
33
#include "city.h"
25
34
#include "stacklist.h"
31
40
//#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
32
41
#define debug(x)
33
42
 
34
 
Path::Path() {}
 
43
Path::Path()
 
44
{
 
45
  d_moves_exhausted_at_point = 0;
 
46
}
35
47
 
36
48
Path::Path(XML_Helper* helper)
37
49
{
39
51
    std::istringstream sx, sy;
40
52
    std::string s;
41
53
 
 
54
    helper->getData(d_moves_exhausted_at_point, "moves_exhausted_at_point");
42
55
    helper->getData(i, "size");
43
56
 
44
57
    helper->getData(s, "x");
74
87
 
75
88
    retval &= helper->openTag("path");
76
89
    retval &= helper->saveData("size", size());
 
90
    retval &= helper->saveData("moves_exhausted_at_point", 
 
91
                               d_moves_exhausted_at_point);
77
92
    retval &= helper->saveData("x", sx.str());
78
93
    retval &= helper->saveData("y", sy.str());
79
94
    retval &= helper->closeTag();
148
163
    {
149
164
      Vector<int> dest = **it;
150
165
      City *c = Citylist::getInstance()->getObjectAt(dest.x, dest.y);
151
 
      if (c && c->getPlayer() != s->getPlayer())
 
166
      if (c && c->getOwner() != s->getOwner())
152
167
        continue;
153
168
      else
154
169
        break;
156
171
  if (it == rend())
157
172
    {
158
173
      //well, it looks like all of our points were in enemy cities
159
 
      s->setMovesExhaustedAtPoint(0);
 
174
      setMovesExhaustedAtPoint(0);
160
175
      flClear();
161
176
    }
162
177
  else
167
182
  return;
168
183
}
169
184
 
170
 
Uint32 Path::calculate (Stack* s, Vector<int> dest, bool zigzag)
 
185
Uint32 Path::calculateToCity (Stack *s, Location *c, bool zigzag)
171
186
{
172
 
    int mp;
173
 
    Vector<int> start = s->getPos();
174
 
    debug("path from "<<start.x<<","<<start.y<<" to "<<dest.x<<","<<dest.y)
175
 
        
176
 
    flClear();
177
 
    int width = GameMap::getWidth();
178
 
    int height = GameMap::getHeight();
179
 
    d_bonus = s->calculateMoveBonus();
180
 
    //if (isBlocked(s, dest.x, dest.y, dest.x, dest.y))
181
 
      //{
182
 
        //s->setMovesExhaustedAtPoint(0);
183
 
        //return 0;
184
 
      //}
185
 
    
186
 
    // Some notes concerning the path finding algorithm. The algorithm
187
 
    // uses two different lists. There is a distance array, which contains how
188
 
    // many MP one needs to get to the location (x,y), and a process queue that
189
 
    // tells you at what point the number of movement points is calculated next.
190
 
    //
191
 
    // What we basically do is to start at the stack's position and calculate
192
 
    // the distance (i.e. MP needed to get there) in circles around the starting
193
 
    // position with the circles becoming increasingly larger. In detail, we
194
 
    // start by appending the starting position in the queue of positions to be
195
 
    // processed. Then, recursively, we take the first point in the queue and
196
 
    // recalculate the distance for all bordering tiles, assuming that we go
197
 
    // over this point and overwriting their current value if it is larger
198
 
    // than what we find now. Then, we append each modified tile to the queue of
199
 
    // tiles to be processed and continue. We stop when there are no more tiles
200
 
    // to process.
201
 
    //
202
 
    // Finally, all that is left is finding the minimum distance way from start
203
 
    // point to destination.
204
 
    
205
 
    // the conversion between x/y coordinates and index is (size is map size)
206
 
    // index = y*width + x    <=>    x = index % width;   y = index / width
207
 
    int length = width*height;
208
 
    int distance[length];
209
 
    std::queue<Vector<int> > process;
210
 
    bool flying = s->isFlying();
211
 
 
212
 
    // initial filling of the distance vector
213
 
    for (int i = 0; i < width*height; i++)
214
 
    {
215
 
        // -1 means don't know yet
216
 
        // -2 means can't go there at all
217
 
        // 0 or more is number of movement points needed to get there
218
 
        distance[i] = -1;
219
 
        if (isBlocked(s, i % width, i/width, dest.x, dest.y))
220
 
            distance[i] = -2;
221
 
    }
222
 
    distance[start.y*width+start.x] = 0;
223
 
    
224
 
    // now the main loop
225
 
    process.push(Vector<int>(start.x, start.y));
226
 
    while (!process.empty())
227
 
    {
228
 
        Vector<int> pos = process.front();
229
 
        process.pop();                          // remove the first item
230
 
        
231
 
        int dxy = distance[pos.y*width+pos.x];   // always >= 0
232
 
 
233
 
        for (int sx = pos.x-1; sx <= pos.x+1; sx++)
234
 
        {
235
 
            if (sx < 0 || sx >= width)
236
 
                continue;
237
 
 
238
 
            for (int sy = pos.y-1; sy <= pos.y+1; sy++)
239
 
            {
240
 
                if (sy < 0 || sy >= height)
241
 
                    continue;
242
 
                
243
 
                if (sx == pos.x && sy == pos.y)
244
 
                  continue;
245
 
 
246
 
                //am i blocked from entering sx,sy from pos?
247
 
                if (!flying && isBlockedDir(pos.x, pos.y, sx, sy))
248
 
                  continue;
249
 
 
250
 
                int dsxy = distance[sy*width+sx];
251
 
                if (dsxy < -1)
252
 
                    continue; // can't move there anyway
253
 
 
254
 
                if (zigzag == false)
 
187
  int min_dist = -1;
 
188
  Vector<int> shortest = c->getPos();
 
189
 
 
190
  for (unsigned int i = 0; i < c->getSize(); i++)
 
191
    for (unsigned int j = 0; j < c->getSize(); j++)
 
192
      {
 
193
        int distance = dist (s->getPos(), c->getPos() + Vector<int>(i, j));
 
194
        if (distance > 0)
 
195
          {
 
196
            if (distance < min_dist || min_dist == -1)
 
197
              {
 
198
                min_dist = distance;
 
199
                shortest = c->getPos() + Vector<int>(i, j);
 
200
              }
 
201
          }
 
202
      }
 
203
  int mp = calculate(s, shortest, zigzag);
 
204
  if (mp <= 0)
 
205
    {
 
206
      //okay.. try really hard
 
207
      min_dist = -1;
 
208
      for (unsigned int i = 0; i < c->getSize(); i++)
 
209
        for (unsigned int j = 0; j < c->getSize(); j++)
 
210
          {
 
211
            int dist = calculate(s, c->getPos() + Vector<int>(i, j), zigzag);
 
212
            if (dist > 0)
 
213
              {
 
214
                if (dist < min_dist || min_dist == -1)
255
215
                  {
256
 
                    Vector<int> diff = pos - Vector<int>(sx, sy);
257
 
                    if (diff.x && diff.y)
258
 
                      continue;
 
216
                    min_dist = dist;
 
217
                    shortest = c->getPos() + Vector<int>(i, j);
259
218
                  }
260
 
                int newDsxy = dxy;
261
 
                mp = pointsToMoveTo(s, pos.x, pos.y, sx, sy);
262
 
                if (mp >= 0)
263
 
                  newDsxy += mp;
264
 
                
265
 
                if (dsxy == -1 || dsxy > newDsxy)
266
 
                {
267
 
                    distance[sy*width+sx] = newDsxy;
268
 
 
269
 
                    // append the item to the queue
270
 
                    process.push(Vector<int>(sx, sy));
271
 
                }
272
 
            }
273
 
        }
274
 
    }
275
 
    
276
 
    // The distance array is now completely populated.
277
 
    // What we have to do now is find the shortest path to the destination.
278
 
    // We do that by starting at the destination and moving at each step to
279
 
    // the neighbour closest to the start.
280
 
 
281
 
    int dist = distance[dest.y * width + dest.x];
282
 
    if (dist < 0)
283
 
      {
284
 
        s->setMovesExhaustedAtPoint(0);
285
 
        return 0;
286
 
      }
287
 
 
288
 
    // choose the order in which we process directions so as to favour
289
 
    // diagonals over straight lines
290
 
    std::list<Vector<int> > diffs;
291
 
    if (zigzag)
292
 
      {
293
 
        diffs.push_back(Vector<int>(-1, -1));
294
 
        diffs.push_back(Vector<int>(-1, 1));
295
 
        diffs.push_back(Vector<int>(1, -1));
296
 
        diffs.push_back(Vector<int>(1, 1));
297
 
        diffs.push_back(Vector<int>(1, 0));
298
 
        diffs.push_back(Vector<int>(-1, 0));
299
 
        diffs.push_back(Vector<int>(0, -1));
300
 
        diffs.push_back(Vector<int>(0, 1));
301
 
      }
302
 
    else
303
 
      {
304
 
        diffs.push_back(Vector<int>(1, 0));
305
 
        diffs.push_back(Vector<int>(-1, 0));
306
 
        diffs.push_back(Vector<int>(0, -1));
307
 
        diffs.push_back(Vector<int>(0, 1));
308
 
      }
309
 
 
310
 
    int x = dest.x;
311
 
    int y = dest.y;
312
 
 
313
 
    while (dist > 0)
314
 
    {
315
 
        Vector<int> *p = new Vector<int>(x,y);
316
 
        push_front(p);
317
 
 
318
 
        int min = dist;
319
 
        int rx = x;
320
 
        int ry = y;
321
 
        for (std::list<Vector<int> >::iterator it = diffs.begin();
322
 
             it != diffs.end(); it++)
323
 
        {
324
 
            int newx = x + (*it).x;//diffs[i][0];
325
 
            int newy = y + (*it).y;//diffs[i][1];
326
 
            if (newx < 0 || newx == width || newy < 0 || newy == height)
327
 
                continue;
328
 
//isBlockedDir is needed to catch crossings from land to sea when not thru a port/city
329
 
            if (!flying && isBlockedDir(x, y, newx, newy))
330
 
                continue;
331
 
            
332
 
            dist = distance[newy*width+newx];
333
 
            if (dist >= 0 && dist < min)
334
 
            {
335
 
                rx = newx;
336
 
                ry = newy;
337
 
                min = dist;
338
 
            }
339
 
        }
340
 
        // found the best spot to go to from
341
 
        x = rx;
342
 
        y = ry;
343
 
        dist = min;
344
 
    }
345
 
 
346
 
    //calculate when the waypoints show no more movement possible
347
 
    Uint32 pathcount = 0;
348
 
    Uint32 moves_left = s->getGroupMoves();
349
 
    for (iterator it = begin(); it != end(); it++)
350
 
      {
351
 
        Uint32 moves = s->calculateTileMovementCost(**it);
352
 
        if (moves_left >= moves)
353
 
          moves_left -= moves;
354
 
        else
355
 
          break;
356
 
        pathcount++;
357
 
      }
358
 
    s->setMovesExhaustedAtPoint(pathcount);
359
 
 
360
 
    debug("...done")
361
 
    return distance[dest.y * width + dest.x];
362
 
}
 
219
              }
 
220
          }
 
221
      mp = calculate(s, shortest, zigzag);
 
222
    }
 
223
  return mp;
 
224
}
 
225
 
 
226
Uint32 Path::calculate (Stack* s, Vector<int> dest, bool zigzag)
 
227
{
 
228
  int mp;
 
229
  Vector<int> start = s->getPos();
 
230
  debug("path from "<<start.x<<","<<start.y<<" to "<<dest.x<<","<<dest.y)
 
231
 
 
232
    flClear();
 
233
  //can we get there with one move?
 
234
  if (dist(s->getPos(), dest) == 1 && canMoveThere(s, dest) == true)
 
235
    {
 
236
      Vector<int> *p = new Vector<int>(dest);
 
237
      push_back(p);
 
238
      setMovesExhaustedAtPoint(1);
 
239
      return 1;
 
240
    }
 
241
  int width = GameMap::getWidth();
 
242
  int height = GameMap::getHeight();
 
243
  d_bonus = s->calculateMoveBonus();
 
244
  //if (isBlocked(s, dest.x, dest.y, dest.x, dest.y))
 
245
  //{
 
246
  //s->setMovesExhaustedAtPoint(0);
 
247
  //return 0;
 
248
  //}
 
249
 
 
250
  // Some notes concerning the path finding algorithm. The algorithm
 
251
  // uses two different lists. There is a distance array, which contains how
 
252
  // many MP one needs to get to the location (x,y), and a process queue that
 
253
  // tells you at what point the number of movement points is calculated next.
 
254
  //
 
255
  // What we basically do is to start at the stack's position and calculate
 
256
  // the distance (i.e. MP needed to get there) in circles around the starting
 
257
  // position with the circles becoming increasingly larger. In detail, we
 
258
  // start by appending the starting position in the queue of positions to be
 
259
  // processed. Then, recursively, we take the first point in the queue and
 
260
  // recalculate the distance for all bordering tiles, assuming that we go
 
261
  // over this point and overwriting their current value if it is larger
 
262
  // than what we find now. Then, we append each modified tile to the queue of
 
263
  // tiles to be processed and continue. We stop when there are no more tiles
 
264
  // to process.
 
265
  //
 
266
  // Finally, all that is left is finding the minimum distance way from start
 
267
  // point to destination.
 
268
 
 
269
  // the conversion between x/y coordinates and index is (size is map size)
 
270
  // index = y*width + x    <=>    x = index % width;   y = index / width
 
271
  int length = width*height;
 
272
  int distance[length];
 
273
  std::queue<Vector<int> > process;
 
274
  bool flying = s->isFlying();
 
275
 
 
276
  // initial filling of the distance vector
 
277
  for (int i = 0; i < width*height; i++)
 
278
    {
 
279
      // -1 means don't know yet
 
280
      // -2 means can't go there at all
 
281
      // 0 or more is number of movement points needed to get there
 
282
      distance[i] = -1;
 
283
      if (isBlocked(s, i % width, i/width, dest.x, dest.y))
 
284
        distance[i] = -2;
 
285
    }
 
286
  distance[start.y*width+start.x] = 0;
 
287
 
 
288
  // now the main loop
 
289
  process.push(Vector<int>(start.x, start.y));
 
290
  while (!process.empty())
 
291
    {
 
292
      Vector<int> pos = process.front();
 
293
      process.pop();                          // remove the first item
 
294
 
 
295
      int dxy = distance[pos.y*width+pos.x];   // always >= 0
 
296
 
 
297
      for (int sx = pos.x-1; sx <= pos.x+1; sx++)
 
298
        {
 
299
          if (sx < 0 || sx >= width)
 
300
            continue;
 
301
 
 
302
          for (int sy = pos.y-1; sy <= pos.y+1; sy++)
 
303
            {
 
304
              if (sy < 0 || sy >= height)
 
305
                continue;
 
306
 
 
307
              if (sx == pos.x && sy == pos.y)
 
308
                continue;
 
309
 
 
310
              //am i blocked from entering sx,sy from pos?
 
311
              if (!flying && isBlockedDir(pos.x, pos.y, sx, sy))
 
312
                continue;
 
313
 
 
314
              int dsxy = distance[sy*width+sx];
 
315
              if (dsxy < -1)
 
316
                continue; // can't move there anyway
 
317
 
 
318
              if (zigzag == false)
 
319
                {
 
320
                  Vector<int> diff = pos - Vector<int>(sx, sy);
 
321
                  if (diff.x && diff.y)
 
322
                    continue;
 
323
                }
 
324
              int newDsxy = dxy;
 
325
              mp = pointsToMoveTo(s, pos.x, pos.y, sx, sy);
 
326
              if (mp >= 0)
 
327
                newDsxy += mp;
 
328
 
 
329
              if (dsxy == -1 || dsxy > newDsxy)
 
330
                {
 
331
                  distance[sy*width+sx] = newDsxy;
 
332
 
 
333
                  // append the item to the queue
 
334
                  process.push(Vector<int>(sx, sy));
 
335
                }
 
336
            }
 
337
        }
 
338
    }
 
339
 
 
340
  // The distance array is now completely populated.
 
341
  // What we have to do now is find the shortest path to the destination.
 
342
  // We do that by starting at the destination and moving at each step to
 
343
  // the neighbour closest to the start.
 
344
 
 
345
  int dist = distance[dest.y * width + dest.x];
 
346
  if (dist < 0)
 
347
    {
 
348
      setMovesExhaustedAtPoint(0);
 
349
      return 0;
 
350
    }
 
351
 
 
352
  // choose the order in which we process directions so as to favour
 
353
  // diagonals over straight lines
 
354
  std::list<Vector<int> > diffs;
 
355
  if (zigzag)
 
356
    {
 
357
      diffs.push_back(Vector<int>(-1, -1));
 
358
      diffs.push_back(Vector<int>(-1, 1));
 
359
      diffs.push_back(Vector<int>(1, -1));
 
360
      diffs.push_back(Vector<int>(1, 1));
 
361
      diffs.push_back(Vector<int>(1, 0));
 
362
      diffs.push_back(Vector<int>(-1, 0));
 
363
      diffs.push_back(Vector<int>(0, -1));
 
364
      diffs.push_back(Vector<int>(0, 1));
 
365
    }
 
366
  else
 
367
    {
 
368
      diffs.push_back(Vector<int>(1, 0));
 
369
      diffs.push_back(Vector<int>(-1, 0));
 
370
      diffs.push_back(Vector<int>(0, -1));
 
371
      diffs.push_back(Vector<int>(0, 1));
 
372
    }
 
373
 
 
374
  int x = dest.x;
 
375
  int y = dest.y;
 
376
 
 
377
  while (dist > 0)
 
378
    {
 
379
      Vector<int> *p = new Vector<int>(x,y);
 
380
      push_front(p);
 
381
 
 
382
      int min = dist;
 
383
      int rx = x;
 
384
      int ry = y;
 
385
      for (std::list<Vector<int> >::iterator it = diffs.begin();
 
386
           it != diffs.end(); it++)
 
387
        {
 
388
          int newx = x + (*it).x;//diffs[i][0];
 
389
          int newy = y + (*it).y;//diffs[i][1];
 
390
          if (newx < 0 || newx == width || newy < 0 || newy == height)
 
391
            continue;
 
392
          //isBlockedDir is needed to catch crossings from land to sea when not thru a port/city
 
393
          if (!flying && isBlockedDir(x, y, newx, newy))
 
394
            continue;
 
395
 
 
396
          dist = distance[newy*width+newx];
 
397
          if (dist >= 0 && dist < min)
 
398
            {
 
399
              rx = newx;
 
400
              ry = newy;
 
401
              min = dist;
 
402
            }
 
403
        }
 
404
      // found the best spot to go to from
 
405
      x = rx;
 
406
      y = ry;
 
407
      dist = min;
 
408
    }
 
409
 
 
410
  //calculate when the waypoints show no more movement possible
 
411
  Uint32 pathcount = 0;
 
412
  Uint32 moves_left = s->getGroupMoves();
 
413
  for (iterator it = begin(); it != end(); it++)
 
414
    {
 
415
      Uint32 moves = s->calculateTileMovementCost(**it);
 
416
      if (moves_left >= moves)
 
417
        moves_left -= moves;
 
418
      else
 
419
        break;
 
420
      pathcount++;
 
421
    }
 
422
  setMovesExhaustedAtPoint(pathcount);
 
423
 
 
424
  debug("...done");
 
425
  return distance[dest.y * width + dest.x];
 
426
}
 
427
 
 
428
void Path::eraseFirstPoint()
 
429
{
 
430
  flErase(begin());
 
431
 
 
432
  if (getMovesExhaustedAtPoint() > 0)
 
433
    setMovesExhaustedAtPoint(getMovesExhaustedAtPoint()-1);
 
434
}
 
435
 
 
436
 
363
437
 
364
438
//am i blocked from entering destx,desty from x,y when i'm not flying?
365
439
bool Path::isBlockedDir(int x, int y, int destx, int desty) const
370
444
    {
371
445
      int idx = 0;
372
446
      if (diffx == -1 && diffy == -1)
373
 
        idx = 0;
 
447
        idx = 0;
374
448
      else if (diffx == -1 && diffy == 0)
375
 
        idx = 1;
 
449
        idx = 1;
376
450
      else if (diffx == -1 && diffy == 1)
377
 
        idx = 2;
 
451
        idx = 2;
378
452
      else if (diffx == 0 && diffy == 1)
379
 
        idx = 3;
 
453
        idx = 3;
380
454
      else if (diffx == 0 && diffy == -1)
381
 
        idx = 4;
 
455
        idx = 4;
382
456
      else if (diffx == 1 && diffy == -1)
383
 
        idx = 5;
 
457
        idx = 5;
384
458
      else if (diffx == 1 && diffy == 0)
385
 
        idx = 6;
 
459
        idx = 6;
386
460
      else if (diffx == 1 && diffy == 1)
387
 
        idx = 7;
 
461
        idx = 7;
388
462
      else
389
463
        return false;
390
464
      return GameMap::getInstance()->getTile(x, y)->d_blocked[idx];
395
469
 
396
470
bool Path::isBlocked(const Stack* s, int x, int y, int destx, int desty) const
397
471
{
398
 
    const Maptile* tile = GameMap::getInstance()->getTile(x,y);
399
 
 
400
 
    // Return true on every condition which may prevent the stack from
401
 
    // entering the tile, which are...
402
 
 
403
 
    // TODO: you can extract quite some amount of time here with a clever
404
 
    // search algorithm for stacklist
405
 
    Stack* target = Stacklist::getObjectAt(x,y);
406
 
    if (target)
407
 
    {
408
 
        // ...enemy stacks which stand in the way...
409
 
        if ((s->getPlayer() != target->getPlayer())
410
 
            && ((x != destx) || (y != desty)))
411
 
            return true;
412
 
 
413
 
        // ...friendly stacks which are too big to merge with...
414
 
        if ((s->getPlayer() == target->getPlayer())
415
 
            && (s->size() + target->size() > MAX_STACK_SIZE))
416
 
            return true;
417
 
    }
418
 
 
419
 
    //...enemy cities
420
 
    // saves some computation time here
421
 
    if (tile->getBuilding() == Maptile::CITY)
422
 
    {
423
 
        City* c = Citylist::getInstance()->getObjectAt(x,y);
424
 
        if (c && (c->getPlayer() != s->getPlayer())
425
 
            && ((x != destx) || (y != desty)))
426
 
            return true;
427
 
    }
428
 
 
429
 
    //no obstacles??? well, then...
430
 
    return false;
 
472
  const Maptile* tile = GameMap::getInstance()->getTile(x,y);
 
473
 
 
474
  // Return true on every condition which may prevent the stack from
 
475
  // entering the tile, which are...
 
476
 
 
477
  // TODO: you can extract quite some amount of time here with a clever
 
478
  // search algorithm for stacklist
 
479
  Stack* target = Stacklist::getObjectAt(x,y);
 
480
  if (target)
 
481
    {
 
482
      // ...enemy stacks which stand in the way...
 
483
      if ((s->getOwner() != target->getOwner())
 
484
          && ((x != destx) || (y != desty)))
 
485
        return true;
 
486
 
 
487
      //the computer walks around any too-big stacks of it's own
 
488
      //unless it's the final destination.
 
489
      if (s->getOwner() == target->getOwner()
 
490
          && s->canJoin(target) == false && 
 
491
          s->getOwner()->getType() != Player::HUMAN) 
 
492
        {
 
493
          if (Vector<int>(destx, desty) != Vector<int>(x,y))
 
494
            return true;
 
495
        }
 
496
 
 
497
    }
 
498
 
 
499
  //...enemy cities
 
500
  // saves some computation time here
 
501
  if (tile->getBuilding() == Maptile::CITY)
 
502
    {
 
503
      City* c = Citylist::getInstance()->getObjectAt(x,y);
 
504
      if (c && (c->getOwner() != s->getOwner())
 
505
          && ((x != destx) || (y != desty)))
 
506
        return true;
 
507
    }
 
508
 
 
509
  //no obstacles??? well, then...
 
510
  return false;
431
511
}
432
512
 
433
513
int Path::pointsToMoveTo(const Stack *s, int x, int y, int destx, int desty) const
434
514
{
435
515
  Uint32 moves;
436
 
    const Maptile* tile = GameMap::getInstance()->getTile(destx,desty);
437
 
    
438
 
    if (x == destx && y == desty) //probably shouldn't happen
439
 
      return 0;
440
 
 
441
 
    moves = tile->getMoves();
442
 
 
443
 
    // does everything in the stack have a bonus to move onto this square?
444
 
    if (tile->getMaptileType() & d_bonus && moves != 1)
445
 
        return 2;
446
 
 
447
 
    return moves;
 
516
  const Maptile* tile = GameMap::getInstance()->getTile(destx,desty);
 
517
 
 
518
  if (x == destx && y == desty) //probably shouldn't happen
 
519
    return 0;
 
520
 
 
521
  moves = tile->getMoves();
 
522
 
 
523
  // does everything in the stack have a bonus to move onto this square?
 
524
  if (tile->getMaptileType() & d_bonus && moves != 1)
 
525
    return 2;
 
526
 
 
527
  return moves;
448
528
}
449
529
 
450
530
// End of file