"docs/userguides/logparam.md" did not exist on "8dab10cc2096a62d753ddd072843fb5f5fa4cbbd"
Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <stdio.h>
#include "distance_map.h"
#include "movement_logic.h"
#include "util.h"
// Erratic tunneling monsters don't care about anything but the border
static position_t next_monster_move_tunnel_erratic(dungeon_t *d, character_t *c) {
position_t next_move;
next_move.x = c->pos.x;
next_move.y = c->pos.y;
while(next_move.x == c->pos.x && next_move.y == c->pos.y) {
next_move.x = randrange(max(1, c->pos.x - 1), min(MAP_WIDTH-2, c->pos.x + 1));
next_move.y = randrange(max(1, c->pos.y - 1), min(MAP_HEIGHT-2, c->pos.y + 1));
}
return next_move;
}
// Erratic non-tunneling monsters have to pick a random open space
static position_t next_monster_move_erratic(dungeon_t *d, character_t *c) {
position_t next_move;
next_move.x = c->pos.x;
next_move.y = c->pos.y;
while(next_move.x == c->pos.x && next_move.y == c->pos.y && !d->hardness[next_move.y][next_move.x]) {
next_move.x = randrange(max(1, c->pos.x - 1), min(MAP_WIDTH-2, c->pos.x + 1));
next_move.y = randrange(max(1, c->pos.y - 1), min(MAP_HEIGHT-2, c->pos.y + 1));
}
return next_move;
}
// Smart tunneling monsters move toward the last known position of the player following
// the tunneling distance map. Smart non-tunneling monsters do the same but use the non-tunneling
// distance map
static position_t next_monster_move_smart(dungeon_t *d, character_t *c) {
int i, j;
uint32_t dist_to_target[MAP_HEIGHT][MAP_WIDTH];
dijkstra_from_pos(d, dist_to_target, (has_characteristic(c, TUNNEL)) ? 255 : 1, c->monster->last_seen.x, c->monster->last_seen.y);
position_t best = {c->pos.x, c->pos.y};
int best_dist = dist_to_target[c->pos.y][c->pos.x];
for (i = max(0, c->pos.y-1); i < min(MAP_WIDTH, c->pos.y+2); i++) {
for (j = max(0, c->pos.x-1); j < min(MAP_WIDTH, c->pos.x+2); j++) {
if (dist_to_target[i][j] < best_dist || (dist_to_target[i][j] == best_dist && i == c->pos.y)) {
best_dist = dist_to_target[i][j];
best.x = j;
best.y = i;
}
}
}
return best;
}
// Dumb tunneling monsters move directly toward the player position if they know it, and
// move erratically otherwise
// Dumb non-tunneling monsters do the same, but can't tunnel
static position_t next_monster_move_dumb(dungeon_t *d, character_t *c) {
if (c->monster->last_seen.x == c->pos.x && c->monster->last_seen.y == c->pos.y) {
if (has_characteristic(c, TUNNEL)) {
return next_monster_move_tunnel_erratic(d, c);
} else {
return next_monster_move_erratic(d, c);
}
} else {
position_t next_move;
next_move.x = c->pos.x + sign(c->monster->last_seen.x - c->pos.x);
next_move.y = c->pos.y + sign(c->monster->last_seen.y - c->pos.y);
return next_move;
}
}
position_t monster_move(dungeon_t *d, character_t *c) {
// Handle telepathic monsters
// If the monster is telepathic, update the position of the PC
// Otherwise if it can currently see the PC then update the position
// Otherwise if it is not smart then forget the pc position
if (has_characteristic(c, TELE)) {
c->monster->last_seen = d->player_pos;
} else if (d->pc_sight[c->pos.y][c->pos.x]) {
c->monster->last_seen = d->player_pos;
} else if (!(has_characteristic(c, SMART))) {
c->monster->last_seen = c->pos;
}
// Handle erratic monsters
// If the monster is erratic, then 50% chance to move randomly
// Movement based on whether it can tunnel or not
if (has_characteristic(c, ERRATIC) && randchance(0.5)) {
if (has_characteristic(c, TUNNEL)) {
return next_monster_move_tunnel_erratic(d, c);
} else {
return next_monster_move_erratic(d, c);
}
}
// Handle smart/dumb monsters
if (has_characteristic(c, SMART)) {
return next_monster_move_smart(d, c);
} else {
return next_monster_move_dumb(d, c);
}
return c->pos;
}