1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ultima/nuvie/core/nuvie_defs.h"
24 #include "ultima/nuvie/misc/u6_misc.h"
25 #include "ultima/nuvie/core/map.h"
26 #include "ultima/nuvie/pathfinder/dir_finder.h"
27 
28 namespace Ultima {
29 namespace Nuvie {
30 
31 /** STATIC FUNCTIONS **/
32 
33 /* From a normalized direction xdir,ydir as base, get the normalized direction
34  * towards one of the seven nearby tiles to the left or right of base.
35  * For rotate: -n = left n tiles, n = right n tiles
36  */
get_adjacent_dir(sint8 & xdir,sint8 & ydir,sint8 rotate)37 void DirFinder::get_adjacent_dir(sint8 &xdir, sint8 &ydir, sint8 rotate) {
38 	struct {
39 		sint8 x, y;
40 	} neighbors[8] = { { -1, -1}, { +0, -1}, { +1, -1},
41 		{ +1, +0},/*ACTOR*/ { +1, +1},
42 		{ +0, +1}, { -1, +1}, { -1, +0}
43 	};
44 
45 	for (uint32 start = 0; start < 8; start++)
46 		if (neighbors[start].x == xdir && neighbors[start].y == ydir) {
47 			sint32 dest = start + rotate;
48 			while (dest < 0 || dest > 7)
49 				dest += (dest < 0) ? 8 : -8;
50 			xdir = neighbors[dest].x;
51 			ydir = neighbors[dest].y;
52 			break;
53 		}
54 }
55 
get_nuvie_dir(sint16 xrel,sint16 yrel)56 uint8 DirFinder::get_nuvie_dir(sint16 xrel, sint16 yrel) {
57 	uint8 direction = NUVIE_DIR_N; // default
58 
59 	if (xrel == 0 && yrel == 0) // nowhere
60 		return (direction);
61 	if (xrel == 0) // up or down
62 		direction = (yrel < 0) ? NUVIE_DIR_N : NUVIE_DIR_S;
63 	else if (yrel == 0) // left or right
64 		direction = (xrel < 0) ? NUVIE_DIR_W : NUVIE_DIR_E;
65 	else if (xrel < 0 && yrel < 0)
66 		direction = NUVIE_DIR_NW;
67 	else if (xrel > 0 && yrel < 0)
68 		direction = NUVIE_DIR_NE;
69 	else if (xrel < 0 && yrel > 0)
70 		direction = NUVIE_DIR_SW;
71 	else if (xrel > 0 && yrel > 0)
72 		direction = NUVIE_DIR_SE;
73 	return (direction);
74 }
75 
get_nuvie_dir(uint16 sx,uint16 sy,uint16 tx,uint16 ty,uint8 z)76 uint8 DirFinder::get_nuvie_dir(uint16 sx, uint16 sy, uint16 tx, uint16 ty, uint8 z) {
77 	return DirFinder::get_nuvie_dir(get_wrapped_rel_dir(tx, sx, z), get_wrapped_rel_dir(ty, sy, z));
78 }
79 
80 // oxdir = original xdir, txdir = to xdir
get_turn_towards_dir(sint16 oxdir,sint16 oydir,sint8 txdir,sint8 tydir)81 sint8 DirFinder::get_turn_towards_dir(sint16 oxdir, sint16 oydir, sint8 txdir, sint8 tydir) {
82 	oxdir = clamp(oxdir, -1, 1);
83 	oydir = clamp(oydir, -1, 1);
84 	txdir = clamp(txdir, -1, 1);
85 	tydir = clamp(tydir, -1, 1);
86 	struct {
87 		sint8 x, y;
88 	} dirs[8] = {{ -1, -1}, { +0, -1}, { +1, -1}, { +1, +0}, { +1, +1}, { +0, +1}, { -1, +1}, { -1, +0}};
89 	uint8 t = 0, o = 0;
90 	for (uint8 d = 0; d < 8; d++) {
91 		if (dirs[d].x == oxdir && dirs[d].y == oydir)
92 			o = d;
93 		if (dirs[d].x == txdir && dirs[d].y == tydir)
94 			t = d;
95 	}
96 	sint8 turn = t - o;
97 	if (turn > 4)
98 		turn = -(8 - turn);
99 	return (clamp(turn, -1, 1));
100 }
101 
102 // xdir,ydir = normal direction from->to (simple method)
get_normalized_dir(MapCoord from,MapCoord to,sint8 & xdir,sint8 & ydir)103 void DirFinder::get_normalized_dir(MapCoord from, MapCoord to, sint8 &xdir, sint8 &ydir) {
104 	xdir = clamp(to.x - from.x, -1, 1);
105 	ydir = clamp(to.y - from.y, -1, 1);
106 
107 	/*    uint16 dx = from.xdistance(to), dy = from.ydistance(to);
108 	    if(dx > 0 && dy > 0)
109 	    {
110 	        if(dx > dy) xdir = 0;
111 	        else if(dx < dy) ydir = 0;
112 	    }*/
113 }
114 
115 } // End of namespace Nuvie
116 } // End of namespace Ultima
117