Skip to content

Commit

Permalink
New code macro grid_distance, and renamed 2d_box_distance (dkfans#2734)
Browse files Browse the repository at this point in the history
They are Manhattan and Chebyshev.
  • Loading branch information
eddebaby authored Nov 23, 2023
1 parent 7477dec commit 010cf46
Show file tree
Hide file tree
Showing 31 changed files with 170 additions and 148 deletions.
60 changes: 30 additions & 30 deletions src/ariadne_wallhug.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ static int hug_round_sub(struct Thing *creatng, MapSubtlCoord *pos1_stl_x, MapSu

unsigned short quadrant = (((LbArcTanAngle(pos2_stl_x - *pos1_stl_x, pos2_stl_y - *pos1_stl_y) & LbFPMath_AngleMask) + 256) >> 9) & 3;

int v20 = max(abs(*pos1_stl_x - pos2_stl_x), abs(*pos1_stl_y - pos2_stl_y));
int v20 = chessboard_distance(*pos1_stl_x, *pos1_stl_y, pos2_stl_x, pos2_stl_y);
if ((int)abs(v20) <= *delta && hug_can_move_on(
creatng,
3 * small_around[quadrant].delta_x + *pos1_stl_x,
Expand All @@ -200,7 +200,7 @@ static int hug_round_sub(struct Thing *creatng, MapSubtlCoord *pos1_stl_x, MapSu
*pos1_stl_x += 3 * small_around[quadrant].delta_x;
*pos1_stl_y += 3 * small_around[quadrant].delta_y;

*delta = max(abs(*pos1_stl_x - pos2_stl_x), abs(*pos1_stl_y - pos2_stl_y));
*delta = chessboard_distance(*pos1_stl_x, *pos1_stl_y, pos2_stl_x, pos2_stl_y);

*v58 = 1;
}
Expand Down Expand Up @@ -255,8 +255,8 @@ static int hug_round(struct Thing *creatng, struct Coord3d *pos1, struct Coord3d
int round_idx_plus1 = (round_idx + 1) & 3;
int round_idx_minus1 = (round_idx - 1) & 3;

MapSubtlDelta max_delta_1 = max(abs(pos1_stl_x - pos2_stl_x), abs(pos1_stl_y - pos2_stl_y)) - 1;
MapSubtlDelta max_delta_2 = max(abs(pos1_stl_x_2 - pos2_stl_x), abs(pos1_stl_y_2 - pos2_stl_y)) - 1;
MapSubtlDelta max_delta_1 = chessboard_distance(pos1_stl_x, pos1_stl_y, pos2_stl_x, pos2_stl_y) - 1;
MapSubtlDelta max_delta_2 = chessboard_distance(pos1_stl_x_2, pos1_stl_y_2, pos2_stl_x, pos2_stl_y) - 1;

char v58 = 0;
char v57 = 0;
Expand All @@ -274,8 +274,8 @@ static int hug_round(struct Thing *creatng, struct Coord3d *pos1, struct Coord3d
if (!i)
return -1;

MapSubtlDelta dist_1 = abs(pos1_stl_y - pos2_stl_y) + abs(pos1_stl_x - pos2_stl_x);
MapSubtlDelta dist_2 = abs(pos1_stl_y_2 - pos2_stl_y) + abs(pos1_stl_x_2 - pos2_stl_x);
MapSubtlDelta dist_1 = grid_distance(pos1_stl_x, pos1_stl_y, pos2_stl_x, pos2_stl_y);
MapSubtlDelta dist_2 = grid_distance(pos1_stl_x_2, pos1_stl_y_2, pos2_stl_x, pos2_stl_y);
if (dist_2 >= dist_1)
{
pos1->x.stl.num = pos1_stl_x;
Expand Down Expand Up @@ -977,7 +977,7 @@ static int get_starting_angle_and_side_of_hug_sub2(
{
creatng->mappos = pos;
v43 = 1;
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
}
}
}
Expand Down Expand Up @@ -1273,7 +1273,7 @@ static signed char get_starting_angle_and_side_of_hug(
{
creatng->mappos = pos_43;
v33 = 1;
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
}
}
}
Expand Down Expand Up @@ -1494,7 +1494,7 @@ static TbBool find_approach_position_to_subtile(const struct Coord3d *srcpos, Ma
struct Map* mapblk = get_map_block_at(tmpos.x.stl.num, tmpos.y.stl.num);
if ((!map_block_invalid(mapblk)) && ((mapblk->flags & SlbAtFlg_Blocking) == 0))
{
MapCoordDelta dist = get_2d_box_distance(srcpos, &tmpos);
MapCoordDelta dist = get_chessboard_distance(srcpos, &tmpos);
if (min_dist > dist)
{
min_dist = dist;
Expand Down Expand Up @@ -1658,13 +1658,13 @@ static TbBool navigation_push_towards_target(struct Navigation *navi, struct Thi
pos1.y.val = navi->pos_next.y.val;
pos1.z.val = navi->pos_next.z.val;
check_forward_for_prospective_hugs(creatng, &pos1, navi->angle, navi->side, SlbAtFlg_Filled|SlbAtFlg_Valuable, speed, crt_owner_flags);
if (get_2d_box_distance(&pos1, &creatng->mappos) > 16)
if (get_chessboard_distance(&pos1, &creatng->mappos) > 16)
{
navi->pos_next.x.val = pos1.x.val;
navi->pos_next.y.val = pos1.y.val;
navi->pos_next.z.val = pos1.z.val;
}
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
int cannot_move = creature_cannot_move_directly_to_with_collide(creatng, &navi->pos_next, SlbAtFlg_Filled|SlbAtFlg_Valuable, crt_owner_flags);

if (cannot_move == 4)
Expand All @@ -1674,7 +1674,7 @@ static TbBool navigation_push_towards_target(struct Navigation *navi, struct Thi
navi->pos_next.z.val = creatng->mappos.z.val;
navi->distance_to_next_pos = 0;
}
navi->dist_to_final_pos = get_2d_box_distance(&creatng->mappos, pos);
navi->dist_to_final_pos = get_chessboard_distance(&creatng->mappos, pos);
if (cannot_move == 1)
{
SubtlCodedCoords stl_num = get_map_index_of_first_block_thing_colliding_with_travelling_to(creatng, &creatng->mappos, &navi->pos_next, SlbAtFlg_Filled|SlbAtFlg_Digable, IGNORE_SLAB_OWNER_CHECK);
Expand Down Expand Up @@ -1713,7 +1713,7 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
switch (navi->navstate)
{
case NavS_Unkn1:
dist_to_next = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
dist_to_next = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
if (dist_to_next >= navi->distance_to_next_pos) {
navi->field_4 = 0;
}
Expand All @@ -1723,7 +1723,7 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
navi->pos_next.x.val = creatng->mappos.x.val + distance_with_angle_to_coord_x(speed, navi->angle);
navi->pos_next.y.val = creatng->mappos.y.val + distance_with_angle_to_coord_y(speed, navi->angle);
navi->pos_next.z.val = get_thing_height_at(creatng, &navi->pos_next);
if (get_2d_box_distance(&creatng->mappos, pos) < get_2d_box_distance(&creatng->mappos, &navi->pos_next))
if (get_chessboard_distance(&creatng->mappos, pos) < get_chessboard_distance(&creatng->mappos, &navi->pos_next))
{
navi->pos_next.x.val = pos->x.val;
navi->pos_next.y.val = pos->y.val;
Expand Down Expand Up @@ -1790,15 +1790,15 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
if (navi->field_4 > 32) {
ERRORLOG("I've been pushing for a very long time now...");
}
if (get_2d_box_distance(&creatng->mappos, &navi->pos_next) <= 16)
if (get_chessboard_distance(&creatng->mappos, &navi->pos_next) <= 16)
{
navi->field_4 = 0;
navigation_push_towards_target(navi, creatng, pos, speed, thing_nav_sizexy(creatng)/2, crt_owner_flags);
}
}
return 1;
case NavS_Unkn2:
dist_to_next = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
dist_to_next = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
if (dist_to_next > 16)
{
if ((dist_to_next > navi->distance_to_next_pos) || creature_cannot_move_directly_to_with_collide(creatng, &navi->pos_next, SlbAtFlg_Filled|SlbAtFlg_Valuable, crt_owner_flags))
Expand All @@ -1814,7 +1814,7 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
}
return 1;
}
if ((get_2d_box_distance(&creatng->mappos, pos) < navi->dist_to_final_pos)
if ((get_chessboard_distance(&creatng->mappos, pos) < navi->dist_to_final_pos)
&& thing_can_continue_direct_line_to(creatng, &creatng->mappos, pos, SlbAtFlg_Filled|SlbAtFlg_Valuable, 1, crt_owner_flags))

{
Expand All @@ -1840,12 +1840,12 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
{
block_flags = get_hugging_blocked_flags(creatng, &tmpos, SlbAtFlg_Filled|SlbAtFlg_Valuable, crt_owner_flags);
set_hugging_pos_using_blocked_flags(&tmpos, creatng, block_flags, thing_nav_sizexy(creatng)/2);
if (get_2d_box_distance(&tmpos, &creatng->mappos) > 16)
if (get_chessboard_distance(&tmpos, &creatng->mappos) > 16)
{
navi->pos_next.x.val = tmpos.x.val;
navi->pos_next.y.val = tmpos.y.val;
navi->pos_next.z.val = tmpos.z.val;
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
return 1;
}
}
Expand Down Expand Up @@ -1896,13 +1896,13 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
tmpos.z.val = navi->pos_next.z.val;
check_forward_for_prospective_hugs(creatng, &tmpos, navi->angle, navi->side, SlbAtFlg_Filled|SlbAtFlg_Valuable, speed, crt_owner_flags);

if (get_2d_box_distance(&tmpos, &creatng->mappos) > 16)
if (get_chessboard_distance(&tmpos, &creatng->mappos) > 16)
{
navi->pos_next.x.val = tmpos.x.val;
navi->pos_next.y.val = tmpos.y.val;
navi->pos_next.z.val = tmpos.z.val;
}
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
cannot_move = creature_cannot_move_directly_to_with_collide(creatng, &navi->pos_next, SlbAtFlg_Filled|SlbAtFlg_Valuable, crt_owner_flags);
if (cannot_move == 4)
{
Expand All @@ -1927,7 +1927,7 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
}
if (cannot_move != 1)
{
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
return 1;
}
stl_num = get_map_index_of_first_block_thing_colliding_with_travelling_to(creatng, &creatng->mappos, &navi->pos_next, SlbAtFlg_Filled|SlbAtFlg_Digable, IGNORE_SLAB_OWNER_CHECK);
Expand All @@ -1939,14 +1939,14 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
navi->angle = get_angle_xy_to(&creatng->mappos, &navi->pos_next);
navi->field_2 = 0;
navi->field_3 = 0;
navi->distance_to_next_pos = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
navi->distance_to_next_pos = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
navi->navstate = NavS_Unkn4;
return 1;
case NavS_Unkn4:
dist_to_next = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
dist_to_next = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
if (dist_to_next > 16)
{
if (get_2d_box_distance(&creatng->mappos, &navi->pos_next) > navi->distance_to_next_pos
if (get_chessboard_distance(&creatng->mappos, &navi->pos_next) > navi->distance_to_next_pos
|| creature_cannot_move_directly_to_with_collide(creatng, &navi->pos_next, SlbAtFlg_Filled|SlbAtFlg_Valuable, crt_owner_flags))
{
navi->navstate = NavS_Unkn1;
Expand Down Expand Up @@ -1978,7 +1978,7 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
navi->field_17 = stl_num;
return 2;
case NavS_Unkn3:
dist_to_next = get_2d_box_distance(&creatng->mappos, &navi->pos_next);
dist_to_next = get_chessboard_distance(&creatng->mappos, &navi->pos_next);
if (dist_to_next > 16)
{
navi->angle = get_angle_xy_to(&creatng->mappos, &navi->pos_next);
Expand Down Expand Up @@ -2042,7 +2042,7 @@ long get_next_position_and_angle_required_to_tunnel_creature_to(struct Thing *cr
navi->navstate = NavS_Unkn1;
return 1;
case NavS_Unkn7:
if (get_2d_box_distance(&creatng->mappos, &navi->pos_next) > 16)
if (get_chessboard_distance(&creatng->mappos, &navi->pos_next) > 16)
{
return 1;
}
Expand Down Expand Up @@ -2117,7 +2117,7 @@ static inline void get_hug_side_next_step(MapSubtlCoord dst_stl_x, MapSubtlCoord
MapSubtlCoord curr_stl_x = *ostl_x;
MapSubtlCoord curr_stl_y = *ostl_y;
unsigned short round_idx = small_around_index_in_direction(curr_stl_x, curr_stl_y, dst_stl_x, dst_stl_y);
int dist = max(abs(curr_stl_x - dst_stl_x), abs(curr_stl_y - dst_stl_y));
int dist = chessboard_distance(curr_stl_x, curr_stl_y, dst_stl_x, dst_stl_y);
int dx = small_around[round_idx].delta_x;
int dy = small_around[round_idx].delta_y;
// If we can follow direction straight to the target, and we will get closer to it, then do it
Expand All @@ -2126,7 +2126,7 @@ static inline void get_hug_side_next_step(MapSubtlCoord dst_stl_x, MapSubtlCoord
curr_stl_x += STL_PER_SLB*dx;
curr_stl_y += STL_PER_SLB*dy;
*state = WaHSS_Val1;
*maxdist = max(abs(curr_stl_x - dst_stl_x), abs(curr_stl_y - dst_stl_y));
*maxdist = chessboard_distance(curr_stl_x, curr_stl_y, dst_stl_x, dst_stl_y);
} else
// If met second wall, finish
if (*state == WaHSS_Val1)
Expand Down Expand Up @@ -2166,7 +2166,7 @@ short get_hug_side_options(MapSubtlCoord src_stl_x, MapSubtlCoord src_stl_y, Map
{
SYNCDBG(4,"Starting");

int dist = max(abs(src_stl_x - dst_stl_x), abs(src_stl_y - dst_stl_y));
int dist = chessboard_distance(src_stl_x, src_stl_y, dst_stl_x, dst_stl_y);

char state_a = WaHSS_Val0;
MapSubtlCoord stl_a_x = src_stl_x;
Expand Down
20 changes: 20 additions & 0 deletions src/bflib_planar.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ long get_distance_xy(long x1, long y1, long x2, long y2)
return LbDiagonalLength(dx, dy);
}

/**
* This distance is "the number of moves needed by a king to move from one tile to another on a chess board".
*
* This is known as Chebyshev distance (see https://en.wikipedia.org/wiki/Chebyshev_distance for details).
*/
MapCoordDelta get_chessboard_distance(const struct Coord3d *pos1, const struct Coord3d *pos2)
{
return chessboard_distance(pos1->x.val, pos1->y.val, pos2->x.val, pos2->y.val);
}

/**
* This distance is "the number of moves needed by a king to move from one cube to another on a 3d chess board".
*
* This is known as Chebyshev distance (see https://en.wikipedia.org/wiki/Chebyshev_distance and https://en.wikipedia.org/wiki/Three-dimensional_chess for details).
*/
MapCoordDelta get_chessboard_3d_distance(const struct Coord3d *pos1, const struct Coord3d *pos2)
{
return chessboard_3d_distance(pos1->x.val, pos1->y.val, pos1->z.val, pos2->x.val, pos2->y.val, pos2->z.val);
}

/**
* Gives X coordinate of a 3D position shift by given distance into given direction.
* @param distance Specifies the distance to move.
Expand Down
25 changes: 25 additions & 0 deletions src/bflib_planar.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define BFLIB_PLANAR_H

#include "bflib_basics.h"
#include "globals.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -38,6 +39,28 @@ struct TbPoint {
long y;
};
/******************************************************************************/

/**
* This distance is "the number of moves needed by a king to move from one tile to another on a chess board".
*
* This is known as Chebyshev distance (see https://en.wikipedia.org/wiki/Chebyshev_distance for details).
*/
#define chessboard_distance(x1,y1,x2,y2) (max(abs(x1 - x2), abs(y1 - y2)))

/**
* This distance is "the number of moves needed by a king to move from one cube to another on a 3d chess board".
*
* This is known as Chebyshev distance (see https://en.wikipedia.org/wiki/Chebyshev_distance and https://en.wikipedia.org/wiki/Three-dimensional_chess for details).
*/
#define chessboard_3d_distance(x1,y1,z1,x2,y2,z2) (max(max(abs(x1 - x2), abs(y1 - y2)),abs(z1 - z2)))

/**
* This distance is "the number of moves needed to move from one tile on a grid to another tile on a grid; where each move must be directly up, down, left or right (Like D&D)".
*
* This is known as Manhattan distance (see https://simple.wikipedia.org/wiki/Manhattan_distance and https://en.wikipedia.org/wiki/Taxicab_geometry for details).
*/
#define grid_distance(x1,y1,x2,y2) (abs(x1 - x2) + abs(y1 - y2))
/******************************************************************************/
void LbSetRect(struct TbRect *rect, long xLeft, long yTop, long xRight, long yBottom);

long get_angle_symmetric_difference(long angle_a, long angle_b);
Expand All @@ -48,6 +71,8 @@ long distance_with_angle_to_coord_x(long distance, long angle);
long distance_with_angle_to_coord_y(long distance, long angle);

long get_distance_xy(long x1, long x2, long y1, long y2);
MapCoordDelta get_chessboard_distance(const struct Coord3d *pos1, const struct Coord3d *pos2);
MapCoordDelta get_chessboard_3d_distance(const struct Coord3d *pos1, const struct Coord3d *pos2);

long distance3d_with_angles_to_coord_x(long distance, long angle_a, long angle_b);
long distance3d_with_angles_to_coord_y(long distance, long angle_a, long angle_b);
Expand Down
11 changes: 6 additions & 5 deletions src/creature_states.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "globals.h"

#include "bflib_math.h"
#include "bflib_planar.h"
#include "thing_list.h"
#include "creature_control.h"
#include "creature_instances.h"
Expand Down Expand Up @@ -1464,7 +1465,7 @@ short creature_being_dropped(struct Thing *creatng)
{
if (!thing_is_picked_up(leadtng))
{
if (get_2d_box_distance(&creatng->mappos, &leadtng->mappos) > subtile_coord(9,0)) {
if (get_chessboard_distance(&creatng->mappos, &leadtng->mappos) > subtile_coord(9,0)) {
SYNCDBG(3,"Removing %s index %d owned by player %d from group",
thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
remove_creature_from_group(creatng);
Expand Down Expand Up @@ -2082,7 +2083,7 @@ short creature_follow_leader(struct Thing *creatng)
return 0;
}
cctrl->following_leader_since = game.play_gameturn;
MapCoordDelta distance_to_follower_pos = get_2d_box_distance(&creatng->mappos, &follwr_pos);
MapCoordDelta distance_to_follower_pos = get_chessboard_distance(&creatng->mappos, &follwr_pos);
TbBool cannot_reach_leader = creature_cannot_move_directly_to(creatng, &leadtng->mappos);
int speed = get_creature_speed(leadtng);
// If we're too far from the designated position, do a speed run
Expand Down Expand Up @@ -2894,7 +2895,7 @@ short creature_pick_up_spell_to_steal(struct Thing *creatng)
struct Thing* picktng = thing_get(cctrl->pickup_object_id);
TRACE_THING(picktng);
if ( thing_is_invalid(picktng) || ((picktng->state_flags & TF1_IsDragged1) != 0)
|| (get_2d_box_distance(&creatng->mappos, &picktng->mappos) >= 512))
|| (get_chessboard_distance(&creatng->mappos, &picktng->mappos) >= 512))
{
set_start_state(creatng);
return 0;
Expand Down Expand Up @@ -4182,7 +4183,7 @@ static TbBool wander_point_get_random_pos(const struct Wander *wandr, const stru
long irnd = CREATURE_RANDOM(thing, wandr->points_count);
MapSubtlCoord stl_x = wandr->points[irnd].stl_x;
MapSubtlCoord stl_y = wandr->points[irnd].stl_y;
MapSubtlCoord dist = get_2d_box_distance_xy(stl_x, stl_y, prevpos->x.stl.num, prevpos->y.stl.num);
MapSubtlCoord dist = chessboard_distance(stl_x, stl_y, prevpos->x.stl.num, prevpos->y.stl.num);
// Move at least 2 slabs, and prefer distance around 7 slabs
// If previously selected selected_dist is too low, allow any place
if (((dist > 6) && (abs(dist-21) < abs(selected_dist-21))) || (selected_dist <= 6))
Expand Down Expand Up @@ -4299,7 +4300,7 @@ short seek_the_enemy(struct Thing *creatng)
struct Thing* enemytng = thing_update_enemy_to_fight_with(creatng);
if (!thing_is_invalid(enemytng))
{
MapCoordDelta dist = get_2d_box_distance(&enemytng->mappos, &creatng->mappos);
MapCoordDelta dist = get_chessboard_distance(&enemytng->mappos, &creatng->mappos);
if (creature_can_hear_within_distance(creatng, dist))
{
if (cctrl->instance_id == CrInst_NULL)
Expand Down
Loading

0 comments on commit 010cf46

Please sign in to comment.