shortest-path-wise nearest enemy. If no enemy is found in their surroundings,
they just wait.
-Diagonal movement is possible, but takes (40%) longer than orthogonal movement.
-
Once you start a new world, every move of yours is recorded in a file called
"record". Once you re-start the game, all of your previous moves are replayed
automatically up to the point wherere you left the game. To start over in a new
sports a list of keybindings available globally, and additionally via the window
selected as active.
-Hit "w" (per default keybindings) to switch the "active" window to a view that
+Hit "W" (per default keybindings) to switch the "active" window to a view that
allows changing its geometry. One more hit on "w" switches the window to a view
that allows changing its window-specific keybindings. The global keybindings can
be changed in the "Global keys" window, those of the window geometry
MAP_TYPE 0
HEIGHT 64
WIDTH 64
-DIST_ORTHOGONAL 5
-DIST_DIAGONAL 7
A line of "MAP_TYPE" followed by a non-empty token starts the map definition
block. In the future, the second token may differentiate different map types,
but as of right now, only one is available and the value is not interpreted.
The numbers after "HEIGHT" and "WIDTH" give the map's vertical and horizontal
-extensions in cells. They must be >= 1 and <= 256. The numbers after
-"DIST_ORTHOGONAL" and "DIST_DIAGONAL" define the diagonal movement penalty as
-the second value divided by the first. The above values define a penalty ratio
-of 7/5 or 1.4, i.e. it takes 40% longer in turns to move diagonally than
-orthogonally. Set both to the same value to eliminate the diagonal movement
-penalty. A negative penalty to realize weird geometry is possible by setting
-"DIST_DIAGONAL" to a lower value than "DIST_ORTHOGONAL". Both values, however,
-must be >= 1 and <= 255.
+extensions in cells. They must be >= 1 and <= 256.
Here's a typical action definition block:
- enable toggling of window borders
- make log scrollable
+
+- nav_inventory() expects too short inventory string length for i
SERVER_COMMAND wait
SERVER_ARGUMENT 0
-COMMAND move_8
-DESCRIPTION 'move north'
-SERVER_COMMAND move
-SERVER_ARGUMENT 8
-
-COMMAND move_9
+COMMAND move_e
DESCRIPTION 'move north-east'
SERVER_COMMAND move
-SERVER_ARGUMENT 9
+SERVER_ARGUMENT e
-COMMAND move_6
+COMMAND move_d
DESCRIPTION 'move east'
SERVER_COMMAND move
-SERVER_ARGUMENT 6
+SERVER_ARGUMENT d
-COMMAND move_3
+COMMAND move_c
DESCRIPTION 'move south-east'
SERVER_COMMAND move
-SERVER_ARGUMENT 3
-
-COMMAND move_2
-DESCRIPTION 'move south'
-SERVER_COMMAND move
-SERVER_ARGUMENT 2
+SERVER_ARGUMENT c
-COMMAND move_1
+COMMAND move_x
DESCRIPTION 'move south-west'
SERVER_COMMAND move
-SERVER_ARGUMENT 1
+SERVER_ARGUMENT x
-COMMAND move_4
+COMMAND move_s
DESCRIPTION 'move west'
SERVER_COMMAND move
-SERVER_ARGUMENT 4
+SERVER_ARGUMENT s
-COMMAND move_7
+COMMAND move_w
DESCRIPTION 'move north-west'
SERVER_COMMAND move
-SERVER_ARGUMENT 7
+SERVER_ARGUMENT w
COMMAND pick
DESCRIPTION 'pick up'
KEY 270 to_g_keywin
KEY 271 to_wg_keywin
KEY 272 to_wk_keywin
-KEY 119 winconf
+KEY 87 winconf
KEY 62 cyc_win_f
KEY 60 cyc_win_b
KEY 262 scrl_l
KEY 100 drop
KEY 259 inv_u
KEY 258 inv_d
-KEY 99 use
+KEY 117 use
WINDOW i
NAME 'Info'
HEIGHT 0
KEY 112 pick
KEY 58 wait
-KEY 107 move_8
-KEY 117 move_9
-KEY 108 move_6
-KEY 110 move_3
-KEY 106 move_2
-KEY 98 move_1
-KEY 104 move_4
-KEY 121 move_7
+KEY 101 move_e
+KEY 100 move_d
+KEY 99 move_c
+KEY 120 move_x
+KEY 115 move_s
+KEY 119 move_w
KEY 259 map_u
KEY 258 map_d
KEY 260 map_l
KEY 270 to_g_keywin
KEY 271 to_wg_keywin
KEY 272 to_wk_keywin
-KEY 119 winconf
+KEY 87 winconf
KEY 62 cyc_win_f
KEY 60 cyc_win_b
KEY 262 scrl_l
KEY 67 save_conf
KEY 112 pick
KEY 58 wait
-KEY 107 move_8
-KEY 117 move_9
-KEY 108 move_6
-KEY 110 move_3
-KEY 106 move_2
-KEY 98 move_1
-KEY 104 move_4
-KEY 121 move_7
+KEY 101 move_e
+KEY 100 move_d
+KEY 99 move_c
+KEY 120 move_x
+KEY 115 move_s
+KEY 119 move_w
KEY 46 map_c
KEY 100 drop
-KEY 99 use
+KEY 117 use
KEYBINDINGS 'wingeom'
KEY 258 shift_f
KEY 270 to_g_keywin
KEY 271 to_wg_keywin
KEY 272 to_wk_keywin
-KEY 119 winconf
+KEY 87 winconf
KEY 62 cyc_win_f
KEY 60 cyc_win_b
KEY 262 scrl_l
KEY 67 save_conf
KEY 112 pick
KEY 58 wait
-KEY 107 move_8
-KEY 117 move_9
-KEY 108 move_6
-KEY 110 move_3
-KEY 106 move_2
-KEY 98 move_1
-KEY 104 move_4
-KEY 121 move_7
+KEY 101 move_e
+KEY 100 move_d
+KEY 99 move_c
+KEY 120 move_x
+KEY 115 move_s
+KEY 119 move_w
KEY 46 map_c
KEY 100 drop
-KEY 99 use
+KEY 117 use
KEYBINDINGS 'wingeom'
KEY 258 shift_f
KEY 270 to_g_keywin
KEY 271 to_wg_keywin
KEY 272 to_wk_keywin
-KEY 119 winconf
+KEY 87 winconf
KEY 62 cyc_win_f
KEY 60 cyc_win_b
KEY 262 scrl_l
KEY 67 save_conf
KEY 112 pick
KEY 58 wait
-KEY 107 move_8
-KEY 117 move_9
-KEY 108 move_6
-KEY 110 move_3
-KEY 106 move_2
-KEY 98 move_1
-KEY 104 move_4
-KEY 121 move_7
+KEY 101 move_e
+KEY 100 move_d
+KEY 99 move_c
+KEY 120 move_x
+KEY 115 move_s
+KEY 119 move_w
KEY 46 map_c
KEY 100 drop
-KEY 99 use
+KEY 117 use
KEYBINDINGS 'wingeom'
KEY 258 shift_f
KEY 270 to_g_keywin
KEY 271 to_wg_keywin
KEY 272 to_wk_keywin
-KEY 119 winconf
+KEY 87 winconf
KEY 62 cyc_win_f
KEY 60 cyc_win_b
KEY 262 scrl_l
KEY 67 save_conf
KEY 112 pick
KEY 58 wait
-KEY 107 move_8
-KEY 117 move_9
-KEY 108 move_6
-KEY 110 move_3
-KEY 106 move_2
-KEY 98 move_1
-KEY 104 move_4
-KEY 121 move_7
+KEY 101 move_e
+KEY 100 move_d
+KEY 99 move_c
+KEY 120 move_x
+KEY 115 move_s
+KEY 119 move_w
KEY 46 map_c
KEY 100 drop
-KEY 99 use
+KEY 117 use
KEYBINDINGS 'wingeom'
KEY 258 shift_f
MAP_TYPE 0
HEIGHT 64
WIDTH 64
-DIST_ORTHOGONAL 5
-DIST_DIAGONAL 7
PLAYER_TYPE 0
extern void draw_win_map(struct Win * win)
{
- try_resize_winmap(win, world.map.size.y, world.map.size.x);
+ try_resize_winmap(win, world.map.size.y, world.map.size.x * 2);
uint16_t z = 0;
uint16_t x, y;
for (y = 0; y < world.map.size.y; y++)
{
for (x = 0; x < world.map.size.x; x++)
{
- set_ch_on_yx(win, y, x, world.map.cells[z]);
+ set_ch_on_yx(win, y, x * 2 + (y % 2), world.map.cells[z]);
z++;
}
}
}
win->center.y = win->center.y - ('8' == d && win->center.y > 0);
}
- else if (('4' == d || '6' == d) && world.map.size.x > win->frame_size.x)
+ else if (('4' == d || '6' == d) && (world.map.size.x*2) > win->frame_size.x)
{
offset = center_offset(win->center.x,
- world.map.size.x, win->frame_size.x);
+ world.map.size.x*2, win->frame_size.x);
win->center.x = offset + (win->frame_size.x / 2);
- if ('6' == d && win->center.x < world.map.size.x - 1)
+ if ('6' == d && win->center.x < (world.map.size.x * 2) - 1)
{
win->center.x++;
return;
{
struct Win * win_map = get_win_by_id('m');
win_map->center.y = world.player_pos.y;
- win_map->center.x = world.player_pos.x;
+ win_map->center.x = world.player_pos.x * 2;
}
-#define N_DIRS 8
+#define N_DIRS 6
-/* Write into "neighbors" scores of the eight immediate 2D neighbors of the
- * "score_map" cell at "pos_i" (array index), as found in the directions north,
- * north-east, east etc. (clockwise order). "max_score" is used for illegal
- * neighborhoods (i.e. if the direction would lead beyond the map's border).
+/* Write into "neighbors" scores of the N_DIRS immediate neighbors of the
+ * "score_map" cell at "pos_i" (array index), as found in the directions
+ * north-east, east, south-east etc. (clockwise order). Use "max_score" for
+ * illegal neighborhoods (i.e. if direction would lead beyond the map's border).
*/
-static void get_neighbor_scores(uint32_t * score_map, uint16_t pos_i,
- uint32_t max_score, uint32_t * neighbors);
+static void get_neighbor_scores(uint16_t * score_map, uint16_t pos_i,
+ uint16_t max_score, uint16_t * neighbors);
-/* Iterate over scored cells in "score_map" of world.map's 2D geometry. Compare
+/* Iterate over scored cells in "score_map" of world.map's geometry. Compare
* each cell's score against the score of its immediate neighbors in N_DIRS
* directions. If it's neighbors are low enough that the result would be lower
- * than the current value, re-set it to world.map.dist_orthogonal points higher
- * than its lowest-scored orthogonal neighbor or world.map.dist_diagonal points
- * higher than its lowest-scored diagonal neighbor (whatever would result in a
- * lower value). Repeat this whole process until all cells have settled on their
+ * than the current value, re-set it to 1 point higher than its lowest-scored
+ * neighbor- Repeat this whole process until all cells have settled on their
* final score. Ignore cells whose position in "score_map" fits cells of
* unreachable terrain in world.map.cells. Expect "max_score" to be the maximum
* score for cells, marking them as unreachable.
*/
-static void dijkstra_map(uint32_t * score_map, uint32_t max_score);
+static void dijkstra_map(uint16_t * score_map, uint16_t max_score);
/* Return numpad char of direction ("8", "6", "2", "4" etc.) of enemy with the
* shortest path to "mo_origin". If no enemy is around, return 0.
-static void get_neighbor_scores(uint32_t * score_map, uint16_t pos_i,
- uint32_t max_score, uint32_t * neighbors)
+static void get_neighbor_scores(uint16_t * score_map, uint16_t pos_i,
+ uint16_t max_score, uint16_t * neighbors)
{
uint32_t map_size = world.map.size.y * world.map.size.x;
uint8_t i_dir;
for (i_dir = 0; i_dir < N_DIRS; neighbors[i_dir] = max_score, i_dir++);
- uint8_t open_north = pos_i >= world.map.size.x;
- uint8_t open_east = pos_i + 1 % world.map.size.x;
- uint8_t open_south = pos_i + world.map.size.x < map_size;
- uint8_t open_west = pos_i % world.map.size.x;
- if (open_north)
+ uint8_t open_north = pos_i >= world.map.size.x;
+ uint8_t open_east = pos_i + 1 % world.map.size.x;
+ uint8_t open_south = pos_i + world.map.size.x < map_size;
+ uint8_t open_west = pos_i % world.map.size.x;
+ uint8_t is_indented = (pos_i / world.map.size.x) % 2;
+ uint8_t open_diag_west = is_indented || open_west;
+ uint8_t open_diag_east = !is_indented || open_east;
+ if (open_north && open_diag_east)
{
- neighbors[0] = score_map[pos_i - world.map.size.x];
- }
- if (open_north && open_east)
- {
- neighbors[1] = score_map[pos_i - world.map.size.x + 1];
+ neighbors[0] = score_map[pos_i - world.map.size.x + is_indented];
}
if (open_east)
{
- neighbors[2] = score_map[pos_i + 1];
+ neighbors[1] = score_map[pos_i + 1];
}
- if (open_east && open_south)
+ if (open_south && open_diag_east)
{
- neighbors[3] = score_map[pos_i + 1 + world.map.size.x];
+ neighbors[2] = score_map[pos_i + world.map.size.x + is_indented];
}
- if (open_south)
+ if (open_south && open_diag_west)
{
- neighbors[4] = score_map[pos_i + world.map.size.x];
- }
- if (open_south && open_west)
- {
- neighbors[5] = score_map[pos_i + world.map.size.x - 1];
+ neighbors[3] = score_map[pos_i + world.map.size.x - !is_indented];
}
if (open_west)
{
- neighbors[6] = score_map[pos_i - 1];
+ neighbors[4] = score_map[pos_i - 1];
}
- if (open_west && open_north)
+ if (open_north && open_diag_west)
{
- neighbors[7] = score_map[pos_i - 1 - world.map.size.x];
+ neighbors[5] = score_map[pos_i - world.map.size.x - !is_indented];
}
}
-static void dijkstra_map(uint32_t * score_map, uint32_t max_score)
+static void dijkstra_map(uint16_t * score_map, uint16_t max_score)
{
- uint32_t i_scans, neighbors[N_DIRS], min_neighbor_o, min_neighbor_d;
uint32_t map_size = world.map.size.y * world.map.size.x;
- uint16_t pos;
+ uint16_t pos, i_scans, neighbors[N_DIRS], min_neighbor;
uint8_t scores_still_changing = 1;
uint8_t i_dirs;
for (i_scans = 0; scores_still_changing; i_scans++)
if ('.' == world.map.cells[pos])
{
get_neighbor_scores(score_map, pos, max_score, neighbors);
- min_neighbor_d = max_score;
- min_neighbor_o = max_score;
+ min_neighbor = max_score;
for (i_dirs = 0; i_dirs < N_DIRS; i_dirs++)
{
- if (!(i_dirs % 2) && min_neighbor_o > neighbors[i_dirs])
+ if (min_neighbor > neighbors[i_dirs])
{
- min_neighbor_o = neighbors[i_dirs];
+ min_neighbor = neighbors[i_dirs];
}
- else if (i_dirs % 2 && min_neighbor_d > neighbors[i_dirs])
- {
- min_neighbor_d = neighbors[i_dirs];
- }
- }
- if (score_map[pos] > min_neighbor_o + world.map.dist_orthogonal)
- {
- score_map[pos] = min_neighbor_o + world.map.dist_orthogonal;
- scores_still_changing = 1;
}
- if (score_map[pos] > min_neighbor_d + world.map.dist_diagonal)
+ if (score_map[pos] > min_neighbor + 1)
{
- score_map[pos] = min_neighbor_d + world.map.dist_diagonal;
+ score_map[pos] = min_neighbor + 1;
scores_still_changing = 1;
}
}
* (Actors' own cells start with a distance of 0 towards themselves.)
*/
uint32_t map_size = world.map.size.y * world.map.size.x;
- uint32_t max_score = UINT32_MAX - (world.map.dist_diagonal + 1);
- uint32_t * score_map = try_malloc(map_size * sizeof(uint32_t), f_name);
+ uint16_t max_score = UINT16_MAX;
+ uint16_t * score_map = try_malloc(map_size * sizeof(uint16_t), f_name);
uint32_t i;
for (i = 0; i < map_size; i++)
{
dijkstra_map(score_map, max_score);
/* Return direction of "mo_origin"'s lowest-scored neighbor cell. */
- uint32_t neighbors[N_DIRS];
+ uint16_t neighbors[N_DIRS];
uint16_t pos_i = (mo_origin->pos.y * world.map.size.x) + mo_origin->pos.x;
get_neighbor_scores(score_map, pos_i, max_score, neighbors);
free(score_map);
char dir_to_nearest_enemy = 0;
- uint32_t min_neighbor = max_score;
- char * dirs = "89632147"; /* get_neighbor_scores()'s clockwise dir order.*/
+ uint16_t min_neighbor = max_score;
+ char * dirs = "edcxsw"; /* get_neighbor_scores()'s clockwise dir order.*/
for (i = 0; i < N_DIRS; i++)
{
if (min_neighbor > neighbors[i])
{
HEIGHT_SET = 0x02,
WIDTH_SET = 0x04,
- ORTH_SET = 0x08,
- DIAG_SET = 0x10,
NAME_SET = 0x02,
EFFORT_SET = 0x04,
CORPSE_ID_SET = 0x04,
READY_ACT = NAME_SET | EFFORT_SET,
READY_OBJ = NAME_SET | CORPSE_ID_SET | SYMBOL_SET | LIFEPOINTS_SET
| CONSUMABLE_SET | START_N_SET,
- READY_MAP = HEIGHT_SET | WIDTH_SET | ORTH_SET | DIAG_SET
+ READY_MAP = HEIGHT_SET | WIDTH_SET
};
*/
static void test_corpse_ids();
+/* set_members() helper specifically for editing world.map members. */
+static uint8_t set_map_members(char * token0,char * token1,uint8_t * map_flags);
+
/* If "token0" matches "comparand", set world.player_type to int in "token1". */
static uint8_t set_player_type(char * token0, char * comparand, char * token1);
uint8_t * action_flags, uint8_t * map_flags,
struct MapObjDef * mod, struct MapObjAct * moa);
-/* set_members() helper specifically for editing world.map members. */
-static uint8_t set_map_members(char * token0,char * token1,uint8_t * map_flags);
-
/* If "name" fits "moa"->name, set "moa"->func to "func". (Derives MapObjAct
* .func from .name for set_members().
*/
err_line(test, "Value must be >= 1 and <= 256.");
return 1;
}
- else if ( parse_val(token0, token1, "DIST_ORTHOGONAL", map_flags,
- ORTH_SET, '8', (char *) &world.map.dist_orthogonal)
- || parse_val(token0, token1, "DIST_DIAGONAL", map_flags,
- DIAG_SET, '8', (char *) &world.map.dist_diagonal))
- {
- err_line(0 == atoi(token1), "Value must not be zero.");
- return 1;
- }
return 0;
}
}
uint8_t add_half_width = !(world.map.size.y % 2) * (world.map.size.x / 2);
world.map.cells[(size / 2) + add_half_width] = '.';
- uint16_t curpos;
+ struct yx_uint8 pos;
+ uint16_t posi;
char * err = "Map generation reached iteration limit. Change map size?";
uint32_t i;
for (i = 0; ; i++, exit_err(256 * UINT16_MAX == i, err))
{
- y = rrand() % world.map.size.y;
- x = rrand() % world.map.size.x;
- curpos = (y * world.map.size.x) + x;
- if ('~' == world.map.cells[curpos]
- && ( ( curpos >= world.map.size.x
- && '.' == world.map.cells[curpos - world.map.size.x])
- || ( curpos < world.map.size.x * (world.map.size.y-1)
- && '.' == world.map.cells[curpos + world.map.size.x])
- || ( curpos > 0 && curpos % world.map.size.x != 0
- && '.' == world.map.cells[curpos-1])
- || ( curpos < (world.map.size.x * world.map.size.y)
- && (curpos+1) % world.map.size.x != 0
- && '.' == world.map.cells[curpos+1])))
+ pos.y = rrand() % world.map.size.y;
+ pos.x = rrand() % world.map.size.x;
+ posi = (pos.y * world.map.size.x) + pos.x;
+ uint8_t ind = pos.y % 2;
+ uint8_t diag_west = pos.x + ind > 0;
+ uint8_t diag_east = pos.x + ind <= world.map.size.x - 1;
+ if ('~' == world.map.cells[posi]
+ && ( ( pos.y > 0 && diag_east
+ && '.' == world.map.cells[posi - world.map.size.x + ind])
+ || ( pos.x < world.map.size.x - 1
+ && '.' == world.map.cells[posi + 1])
+ || ( pos.y < world.map.size.y - 1 && diag_east
+ && '.' == world.map.cells[posi + world.map.size.x + ind])
+ || ( pos.y > 0 && diag_west
+ && '.' == world.map.cells[posi - world.map.size.x - !ind])
+ || ( pos.x > 0
+ && '.' == world.map.cells[posi - 1])
+ || ( pos.y < world.map.size.y - 1 && diag_west
+ && '.' == world.map.cells[posi + world.map.size.x - !ind])))
{
- if ( y == 0 || y == world.map.size.y - 1
- || x == 0 || x == world.map.size.x - 1)
+ if ( pos.y == 0 || pos.y == world.map.size.y - 1
+ || pos.x == 0 || pos.x == world.map.size.x - 1)
{
break;
}
- world.map.cells[y * world.map.size.x + x] = '.';
+ world.map.cells[posi] = '.';
}
}
}
{
struct yx_uint16 size; /* Map's height/width (use max. 256x256)! */
char * cells; /* Sequence of bytes encoding map cells. */
- uint8_t dist_orthogonal; /* Ratio of the diagonal movement penalty as */
- uint8_t dist_diagonal; /* encoded by (.dist_diagonal/.dist_orthonal). */
};
/* Initialize island map "~" cells representing water and "." cells representing
- * land. The shape of the island is generated randomly by starting with a sea
- * containing one land cell in the middle and then going into a cycle of
- * repeatedly selecting a random cell on the map and transforming it into a land
- * cell if it is horizontally or vertically neighbor to one; the cycle ends when
- * a land cell is due to be created right at the border of the map.
+ * land. The island shape is built randomly by starting with a sea of one land
+ * cell in the middle, then going into a cycle of repeatedly selecting a random
+ * seal cell and transforming it into land if it is neighbor to land; the cycle
+ * ends when a land cell is due to be created right at the border of the map.
*/
extern void init_map();
static void playerbonus_move(char d, uint8_t passable)
{
- char * dsc_dir = "north";
- if ( match_dir(d, &dsc_dir, '6', "east")
- || match_dir(d, &dsc_dir, '2', "south")
- || match_dir(d, &dsc_dir, '4', "west")
- || match_dir(d, &dsc_dir, '7', "north-west")
- || match_dir(d, &dsc_dir, '9', "north-east")
- || match_dir(d, &dsc_dir, '1', "south-west")
- || match_dir(d, &dsc_dir, '3', "south-east"))
+ char * dsc_dir = "north-east";
+ if ( match_dir(d, &dsc_dir, 'd', "east")
+ || match_dir(d, &dsc_dir, 'c', "south-east")
+ || match_dir(d, &dsc_dir, 'x', "south-west")
+ || match_dir(d, &dsc_dir, 's', "west")
+ || match_dir(d, &dsc_dir, 'w', "north-west"))
{
;
}
extern void actor_wait(struct MapObj * mo);
/* Actor "mo" tries to move one step in direction described by char mo->arg
- * (where east is '6', north '8') etc. Move either succeeds, or another actor is
- * encountered and hit (which leads ot its lifepoint decreasing by one and
- * eventually death), or the move fails due to an impassable target square.
+ * (where noth-east is 'e', east 'd' etc.) Move either succeeds, or another
+ * actor is encountered and hit (which leads ot its lifepoint decreasing by one
+ * and eventually death), or the move fails due to an impassable target square.
*/
extern void actor_move(struct MapObj * mo);
*/
static void turn_over();
-/* Helper to turn_over() to determine whether a map object's action effort has
- * reached its end. The simplicity of just comparing map_object->progress to
- * moa->effort is suspended for actor movement, for in this case the effort
- * depends on the diagonal movement penalty expressed in the ratio of
- * world.map.dist_diagonal / world.map.dist_orthogonal. (Movement being diagonal
- * or orthogonal is determined by the ->arg char encoding an even or un-even
- * number digit).
- */
-static uint8_t is_effort_finished(struct MapObjAct * moa,
- struct MapObj * map_object);
-
/* If "msg"'s first part matches "command_name", set player's MapObj's .command
* to the command's id and its .arg to a numerical value following in the latter
* part of "msg" (if no digits are found, use 0); then finish player's turn and
{
moa = moa->next;
}
- if (is_effort_finished(moa, map_object))
+ if (map_object->progress == moa->effort)
{
moa->func(map_object);
map_object->command = 0;
-static uint8_t is_effort_finished(struct MapObjAct * moa,
- struct MapObj * map_object)
-{
- if (moa->func != actor_move)
- {
- if (map_object->progress == moa->effort)
- {
- return 1;
- }
- }
- else if (strchr("8624", map_object->arg))
- {
- if (map_object->progress == moa->effort)
- {
- return 1;
- }
- }
- else if (strchr("1379", map_object->arg))
- {
- uint16_t diagonal_effort = (moa->effort * world.map.dist_diagonal)
- / world.map.dist_orthogonal;
- if (map_object->progress == diagonal_effort)
- {
- return 1;
- }
- }
- return 0;
-}
-
-
-
static uint8_t apply_player_command(char * msg, char * command_name)
{
if (!strncmp(msg, command_name, strlen(command_name)))
extern struct yx_uint8 mv_yx_in_dir(char d, struct yx_uint8 yx)
{
- if (d == '8' && yx.y > 0)
+ if (d == 'e' && yx.y > 0 && (yx.x < UINT8_MAX || !(yx.y % 2)))
{
+ yx.x = yx.x + (yx.y % 2);
yx.y--;
}
- else if (d == '9' && yx.y > 0 && yx.x < UINT8_MAX)
+ else if (d == 'd' && yx.x < UINT8_MAX)
{
- yx.y--;
- yx.x++;
- }
- else if (d == '6' && yx.x < UINT8_MAX)
- {
- yx.x++;
- }
- else if (d == '3' && yx.x < UINT8_MAX && yx.y < UINT8_MAX)
- {
- yx.y++;
yx.x++;
}
- else if (d == '2' && yx.y < UINT8_MAX)
+ else if (d == 'c' && yx.y < UINT8_MAX && (yx.x < UINT8_MAX || !(yx.y % 2)))
{
+ yx.x = yx.x + (yx.y % 2);
yx.y++;
}
- else if (d == '1' && yx.y < UINT8_MAX && yx.x > 0)
+ else if (d == 'x' && yx.y < UINT8_MAX && (yx.x > 0 || yx.y % 2))
{
+ yx.x = yx.x - !(yx.y % 2);
yx.y++;
- yx.x--;
}
- else if (d == '4' && yx.x > 0)
+ else if (d == 's' && yx.x > 0)
{
yx.x--;
}
- else if (d == '7' && yx.x > 0 && yx.y > 0)
+ else if (d == 'w' && yx.y > 0 && (yx.x > 0 || yx.y % 2))
{
+ yx.x = yx.x - !(yx.y % 2);
yx.y--;
- yx.x--;
}
return yx;
}
/* Return 1 if two yx_uint8 coordinates at "a" and "b" are equal, else 0. */
extern uint8_t yx_uint8_cmp(struct yx_uint8 * a, struct yx_uint8 * b);
-/* Return yx_uint8 coordinate one step from "yx" in direction "dir" (numpad
- * digits: north '8', east: '6', etc.) If "dir" is invalid or would wrap the
- * move around the edge of a 2^16x2^16 cells field, "yx" remains unchanged.
+/* Return yx_uint8 coordinate one step from "yx" in direction "dir" ('e':
+ * northeast, 'd': east, 'c': south-east, 'x': south-west, 's': west, ' 'w':
+ * north-west). If "dir" is invalid or would wrap the move around the edge of a
+ * 2^8x2^8 cells field, "yx" remains unchanged.
*/
extern struct yx_uint8 mv_yx_in_dir(char dir, struct yx_uint8 yx);