uint32_t io_teleport_pc(dungeon_t *d) { /* Just for fun. */ pair_t dest; do { dest[dim_x] = rand_range(1, DUNGEON_X - 2); dest[dim_y] = rand_range(1, DUNGEON_Y - 2); } while (charpair(dest)); d->charmap[character_get_y(d->pc)][character_get_x(d->pc)] = NULL; d->charmap[dest[dim_y]][dest[dim_x]] = d->pc; character_set_y(d->pc, dest[dim_y]); character_set_x(d->pc, dest[dim_x]); if (mappair(dest) < ter_floor) { mappair(dest) = ter_floor; } pc_observe_terrain(d->pc, d); dijkstra(d); dijkstra_tunnel(d); return 0; }
void npc_next_pos_line_of_sight_tunnel(dungeon *d, character *c, pair_t next) { pair_t dir; dir[dim_y] = d->PC->position[dim_y] - c->position[dim_y]; dir[dim_x] = d->PC->position[dim_x] - c->position[dim_x]; if (dir[dim_y]) { dir[dim_y] /= abs(dir[dim_y]); } if (dir[dim_x]) { dir[dim_x] /= abs(dir[dim_x]); } dir[dim_x] += next[dim_x]; dir[dim_y] += next[dim_y]; if (hardnesspair(dir) <= 60) { if (hardnesspair(dir)) { hardnesspair(dir) = 0; mappair(dir) = ter_floor_hall; /* Update distance maps because map has changed. */ dijkstra(d); dijkstra_tunnel(d); } next[dim_x] = dir[dim_x]; next[dim_y] = dir[dim_y]; } else { hardnesspair(dir) -= 60; } }
void npc_next_pos_rand(dungeon *d, character *c, pair_t next) { pair_t n; union { uint32_t i; uint8_t a[4]; } r; do { n[dim_y] = next[dim_y]; n[dim_x] = next[dim_x]; r.i = rand(); if (r.a[0] > 85 /* 255 / 3 */) { if (r.a[0] & 1) { n[dim_y]--; } else { n[dim_y]++; } } if (r.a[1] > 85 /* 255 / 3 */) { if (r.a[1] & 1) { n[dim_x]--; } else { n[dim_x]++; } } } while (mappair(n) < ter_floor); next[dim_y] = n[dim_y]; next[dim_x] = n[dim_x]; }
void render_distance_map(dungeon_t *d) { pair_t p; for (p[dim_y] = 0; p[dim_y] < DUNGEON_Y; p[dim_y]++) { for (p[dim_x] = 0; p[dim_x] < DUNGEON_X; p[dim_x]++) { switch (mappair(p)) { case ter_wall: case ter_wall_immutable: putchar(' '); break; case ter_floor: case ter_floor_room: if (d->pc_distance[p[dim_y]][p[dim_x]] < 62) { putchar(distance_to_char[d->pc_distance[p[dim_y]][p[dim_x]]]); } else { putchar('.'); } break; case ter_floor_hall: if (d->pc_distance[p[dim_y]][p[dim_x]] < 62) { putchar(distance_to_char[d->pc_distance[p[dim_y]][p[dim_x]]]); } else { putchar('#'); } break; case ter_debug: printf("Debug character at %d, %d\n", p[dim_y], p[dim_x]); putchar('*'); break; } } putchar('\n'); } }
void render_dungeon(dungeon_t *d) { pair_t p; for (p[dim_y] = 0; p[dim_y] < DUNGEON_Y; p[dim_y]++) { for (p[dim_x] = 0; p[dim_x] < DUNGEON_X; p[dim_x]++) { if (p[dim_x] == d->pc.position[dim_x] && p[dim_y] == d->pc.position[dim_y]) { putchar('@'); } else { switch (mappair(p)) { case ter_wall: case ter_wall_immutable: putchar(' '); break; case ter_floor: case ter_floor_room: putchar('.'); break; case ter_floor_hall: putchar('#'); break; case ter_debug: printf("Debug character at %d, %d\n", p[dim_y], p[dim_x]); putchar('*'); break; } } } putchar('\n'); } }
void npc_next_pos_rand_tunnel(dungeon *d, character *c, pair_t next) { pair_t n; union { uint32_t i; uint8_t a[4]; } r; do { n[dim_y] = next[dim_y]; n[dim_x] = next[dim_x]; r.i = rand(); if (r.a[0] > 85 /* 255 / 3 */) { if (r.a[0] & 1) { n[dim_y]--; } else { n[dim_y]++; } } if (r.a[1] > 85 /* 255 / 3 */) { if (r.a[1] & 1) { n[dim_x]--; } else { n[dim_x]++; } } } while (mappair(n) == ter_wall_immutable); if (hardnesspair(n) <= 85) { if (hardnesspair(n)) { hardnesspair(n) = 0; mappair(n) = ter_floor_hall; /* Update distance maps because map has changed. */ dijkstra(d); dijkstra_tunnel(d); } next[dim_x] = n[dim_x]; next[dim_y] = n[dim_y]; } else { hardnesspair(n) -= 85; } }
static int place_rooms(dungeon_t *d) { pair_t p; uint32_t i; int success; room_t *r; for (success = 0; !success; ) { success = 1; for (i = 0; success && i < d->num_rooms; i++) { r = d->rooms + i; r->position[dim_x] = 1 + rand() % (DUNGEON_X - 2 - r->size[dim_x]); r->position[dim_y] = 1 + rand() % (DUNGEON_Y - 2 - r->size[dim_y]); for (p[dim_y] = r->position[dim_y] - 1; success && p[dim_y] < r->position[dim_y] + r->size[dim_y] + 1; p[dim_y]++) { for (p[dim_x] = r->position[dim_x] - 1; success && p[dim_x] < r->position[dim_x] + r->size[dim_x] + 1; p[dim_x]++) { if (mappair(p) >= ter_floor) { success = 0; empty_dungeon(d); } else if ((p[dim_y] != r->position[dim_y] - 1) && (p[dim_y] != r->position[dim_y] + r->size[dim_y]) && (p[dim_x] != r->position[dim_x] - 1) && (p[dim_x] != r->position[dim_x] + r->size[dim_x])) { mappair(p) = ter_floor_room; hardnesspair(p) = 0; } } } } } return 0; }
static void place_stairs(dungeon_t *d) { pair_t p; do { while ((p[dim_y] = rand_range(1, DUNGEON_Y - 2)) && (p[dim_x] = rand_range(1, DUNGEON_X - 2)) && ((mappair(p) < ter_floor) || (mappair(p) > ter_stairs))) ; mappair(p) = ter_stairs_down; } while (rand_under(1, 3)); do { while ((p[dim_y] = rand_range(1, DUNGEON_Y - 2)) && (p[dim_x] = rand_range(1, DUNGEON_X - 2)) && ((mappair(p) < ter_floor) || (mappair(p) > ter_stairs))) ; mappair(p) = ter_stairs_up; } while (rand_under(1, 4)); }
uint32_t can_see(dungeon_t *d, pair_t voyeur, pair_t exhibitionist, int is_pc) { /* Application of Bresenham's Line Drawing Algorithm. If we can draw * * a line from v to e without intersecting any walls, then v can see * * e. Unfortunately, Bresenham isn't symmetric, so line-of-sight * * based on this approach is not reciprocal (Helmholtz Reciprocity). * * This is a very real problem in roguelike games, and one we're * * going to ignore for now. Algorithms that are symmetrical are far * * more expensive. */ pair_t first, second; pair_t del, f; int16_t a, b, c, i; int16_t visual_range; visual_range = is_pc ? PC_VISUAL_RANGE : NPC_VISUAL_RANGE; first[dim_x] = voyeur[dim_x]; first[dim_y] = voyeur[dim_y]; second[dim_x] = exhibitionist[dim_x]; second[dim_y] = exhibitionist[dim_y]; /* Monsters only use this to see the PC, so we can * * short circuit the tests when they are far away. */ if ((abs(first[dim_x] - second[dim_x]) > visual_range) || (abs(first[dim_y] - second[dim_y]) > visual_range)) { return 0; } /* mappair(first) = ter_debug; mappair(second) = ter_debug; */ if (second[dim_x] > first[dim_x]) { del[dim_x] = second[dim_x] - first[dim_x]; f[dim_x] = 1; } else { del[dim_x] = first[dim_x] - second[dim_x]; f[dim_x] = -1; } if (second[dim_y] > first[dim_y]) { del[dim_y] = second[dim_y] - first[dim_y]; f[dim_y] = 1; } else { del[dim_y] = first[dim_y] - second[dim_y]; f[dim_y] = -1; } if (del[dim_x] > del[dim_y]) { a = del[dim_y] + del[dim_y]; c = a - del[dim_x]; b = c - del[dim_x]; for (i = 0; i <= del[dim_x]; i++) { if (is_pc) { pc_learn_terrain(d->pc, first, mappair(first)); } if ((mappair(first) < ter_floor) && i && (i != del[dim_x])) { return 0; } /* mappair(first) = ter_debug;*/ first[dim_x] += f[dim_x]; if (c < 0) { c += a; } else { c += b; first[dim_y] += f[dim_y]; } } return 1; } else { a = del[dim_x] + del[dim_x]; c = a - del[dim_y]; b = c - del[dim_y]; for (i = 0; i <= del[dim_y]; i++) { if (is_pc) { pc_learn_terrain(d->pc, first, mappair(first)); } if ((mappair(first) < ter_floor) && i && (i != del[dim_y])) { return 0; } /* mappair(first) = ter_debug;*/ first[dim_y] += f[dim_y]; if (c < 0) { c += a; } else { c += b; first[dim_x] += f[dim_x]; } } return 1; } return 1; }
void npc_next_pos_gradient(dungeon *d, npc *c, pair_t next) { /* Handles both tunneling and non-tunneling versions */ pair_t min_next; uint16_t min_cost; if (c->characteristics & NPC_TUNNEL) { min_cost = (d->pc_tunnel[next[dim_y] - 1][next[dim_x]] + (d->hardness[next[dim_y] - 1][next[dim_x]] / 60)); min_next[dim_x] = next[dim_x]; min_next[dim_y] = next[dim_y] - 1; if ((d->pc_tunnel[next[dim_y] + 1][next[dim_x] ] + (d->hardness[next[dim_y] + 1][next[dim_x]] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y] + 1][next[dim_x]] + (d->hardness[next[dim_y] + 1][next[dim_x]] / 60)); min_next[dim_x] = next[dim_x]; min_next[dim_y] = next[dim_y] + 1; } if ((d->pc_tunnel[next[dim_y] ][next[dim_x] + 1] + (d->hardness[next[dim_y] ][next[dim_x] + 1] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y]][next[dim_x] + 1] + (d->hardness[next[dim_y]][next[dim_x] + 1] / 60)); min_next[dim_x] = next[dim_x] + 1; min_next[dim_y] = next[dim_y]; } if ((d->pc_tunnel[next[dim_y] ][next[dim_x] - 1] + (d->hardness[next[dim_y] ][next[dim_x] - 1] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y]][next[dim_x] - 1] + (d->hardness[next[dim_y]][next[dim_x] - 1] / 60)); min_next[dim_x] = next[dim_x] - 1; min_next[dim_y] = next[dim_y]; } if ((d->pc_tunnel[next[dim_y] - 1][next[dim_x] + 1] + (d->hardness[next[dim_y] - 1][next[dim_x] + 1] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y] - 1][next[dim_x] + 1] + (d->hardness[next[dim_y] - 1][next[dim_x] + 1] / 60)); min_next[dim_x] = next[dim_x] + 1; min_next[dim_y] = next[dim_y] - 1; } if ((d->pc_tunnel[next[dim_y] + 1][next[dim_x] + 1] + (d->hardness[next[dim_y] + 1][next[dim_x] + 1] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y] + 1][next[dim_x] + 1] + (d->hardness[next[dim_y] + 1][next[dim_x] + 1] / 60)); min_next[dim_x] = next[dim_x] + 1; min_next[dim_y] = next[dim_y] + 1; } if ((d->pc_tunnel[next[dim_y] - 1][next[dim_x] - 1] + (d->hardness[next[dim_y] - 1][next[dim_x] - 1] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y] - 1][next[dim_x] - 1] + (d->hardness[next[dim_y] - 1][next[dim_x] - 1] / 60)); min_next[dim_x] = next[dim_x] - 1; min_next[dim_y] = next[dim_y] - 1; } if ((d->pc_tunnel[next[dim_y] + 1][next[dim_x] - 1] + (d->hardness[next[dim_y] + 1][next[dim_x] - 1] / 60)) < min_cost) { min_cost = (d->pc_tunnel[next[dim_y] + 1][next[dim_x] - 1] + (d->hardness[next[dim_y] + 1][next[dim_x] - 1] / 60)); min_next[dim_x] = next[dim_x] - 1; min_next[dim_y] = next[dim_y] + 1; } if (hardnesspair(min_next) <= 60) { if (hardnesspair(min_next)) { hardnesspair(min_next) = 0; mappair(min_next) = ter_floor_hall; /* Update distance maps because map has changed. */ dijkstra(d); dijkstra_tunnel(d); } next[dim_x] = min_next[dim_x]; next[dim_y] = min_next[dim_y]; } else { hardnesspair(min_next) -= 60; } } else { /* Make monsters prefer cardinal directions */ if (d->pc_distance[next[dim_y] - 1][next[dim_x] ] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_y]--; return; } if (d->pc_distance[next[dim_y] + 1][next[dim_x] ] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_y]++; return; } if (d->pc_distance[next[dim_y] ][next[dim_x] + 1] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_x]++; return; } if (d->pc_distance[next[dim_y] ][next[dim_x] - 1] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_x]--; return; } if (d->pc_distance[next[dim_y] - 1][next[dim_x] + 1] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_y]--; next[dim_x]++; return; } if (d->pc_distance[next[dim_y] + 1][next[dim_x] + 1] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_y]++; next[dim_x]++; return; } if (d->pc_distance[next[dim_y] - 1][next[dim_x] - 1] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_y]--; next[dim_x]--; return; } if (d->pc_distance[next[dim_y] + 1][next[dim_x] - 1] < d->pc_distance[next[dim_y]][next[dim_x]]) { next[dim_y]++; next[dim_x]--; return; } } }
uint32_t move_pc(dungeon_t *d, uint32_t dir) { pair_t next; uint32_t was_stairs = 0; next[dim_y] = character_get_y(d->pc); next[dim_x] = character_get_x(d->pc); switch (dir) { case 1: case 2: case 3: next[dim_y]++; break; case 4: case 5: case 6: break; case 7: case 8: case 9: next[dim_y]--; break; } switch (dir) { case 1: case 4: case 7: next[dim_x]--; break; case 2: case 5: case 8: break; case 3: case 6: case 9: next[dim_x]++; break; case '<': if (mappair(character_get_pos(d->pc)) == ter_stairs_up) { was_stairs = 1; new_dungeon_level(d, '<'); } break; case '>': if (mappair(character_get_pos(d->pc)) == ter_stairs_down) { was_stairs = 1; new_dungeon_level(d, '>'); } break; } if (was_stairs) { return 0; } if ((dir != '>') && (dir != '<') && (mappair(next) >= ter_floor)) { move_character(d, d->pc, next); dijkstra(d); dijkstra_tunnel(d); return 0; } return 1; }