static int compare_monster_distance(const void *v1, const void *v2) { const character *const *c1 = (const character * const *) v1; const character *const *c2 = (const character * const *) v2; return (dungeon->pc_distance[character_get_y(*c1)][character_get_x(*c1)] - dungeon->pc_distance[character_get_y(*c2)][character_get_x(*c2)]); }
void dir_nearest_wall(dungeon_t *d, character *c, pair_t dir) { dir[dim_x] = dir[dim_y] = 0; if (character_get_x(c) != 1 && character_get_x(c) != DUNGEON_X - 2) { dir[dim_x] = (character_get_x(c) > DUNGEON_X - character_get_x(c) ? 1 : -1); } if (character_get_y(c) != 1 && character_get_y(c) != DUNGEON_Y - 2) { dir[dim_y] = (character_get_y(c) > DUNGEON_Y - character_get_y(c) ? 1 : -1); } }
static void io_list_monsters_display(dungeon_t *d, character **c, uint32_t count) { uint32_t i; char (*s)[40]; /* pointer to array of 40 char */ s = (char (*)[40]) malloc(count * sizeof (*s)); mvprintw(3, 19, " %-40s ", ""); /* Borrow the first element of our array for this string: */ snprintf(s[0], 40, "You know of %d monsters:", count); mvprintw(4, 19, " %-40s ", s); mvprintw(5, 19, " %-40s ", ""); for (i = 0; i < count; i++) { snprintf(s[i], 40, "%16s%c: %2d %s by %2d %s", (character_get_symbol(c[i]) == 'd' ? "A tenacious " : adjectives[rand() % (sizeof (adjectives) / sizeof (adjectives[0]))]), character_get_symbol(c[i]), abs(character_get_y(c[i]) - character_get_y(d->pc)), ((character_get_y(c[i]) - character_get_y(d->pc)) <= 0 ? "North" : "South"), abs(character_get_x(c[i]) - character_get_x(d->pc)), ((character_get_x(c[i]) - character_get_x(d->pc)) <= 0 ? "East" : "West")); if (count <= 13) { /* Handle the non-scrolling case right here. * * Scrolling in another function. */ mvprintw(i + 6, 19, " %-40s ", s[i]); } } if (count <= 13) { mvprintw(count + 6, 19, " %-40s ", ""); mvprintw(count + 7, 19, " %-40s ", "Hit escape to continue."); while (getch() != 27 /* escape */) ; } else { mvprintw(19, 19, " %-40s ", ""); mvprintw(20, 19, " %-40s ", "Arrows to scroll, escape to continue."); io_scroll_monster_list(s, count); } free(s); }
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; }
static void npc_next_pos_17(dungeon *d, npc *c, pair_t next) { /* pass wall; smart; telepathic; tunneling; not erratic */ c->pc_last_known_position[dim_y] = character_get_y(d->PC); c->pc_last_known_position[dim_x] = character_get_x(d->PC); npc_next_pos_line_of_sight(d, c, next); }
void npc_next_pos_line_of_sight(dungeon *d, character *c, pair_t next) { pair_t dir; dir[dim_y] = character_get_y(d->PC) - c->position[dim_y]; dir[dim_x] = character_get_x(d->PC) - 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]); } if (((npc *) c)->characteristics & NPC_PASS_WALL) { next[dim_x] += dir[dim_x]; next[dim_y] += dir[dim_y]; } else { if (mapxy(next[dim_x] + dir[dim_x], next[dim_y] + dir[dim_y]) >= ter_floor) { next[dim_x] += dir[dim_x]; next[dim_y] += dir[dim_y]; } else if (mapxy(next[dim_x] + dir[dim_x], next[dim_y]) >= ter_floor) { next[dim_x] += dir[dim_x]; } else if (mapxy(next[dim_x], next[dim_y] + dir[dim_y]) >= ter_floor) { next[dim_y] += dir[dim_y]; } } }
uint32_t in_corner(dungeon_t *d, character *c) { uint32_t num_immutable; num_immutable = 0; num_immutable += (mapxy(character_get_x(c) - 1, character_get_y(c) ) == ter_wall_immutable); num_immutable += (mapxy(character_get_x(c) + 1, character_get_y(c) ) == ter_wall_immutable); num_immutable += (mapxy(character_get_x(c) , character_get_y(c) - 1) == ter_wall_immutable); num_immutable += (mapxy(character_get_x(c) , character_get_y(c) + 1) == ter_wall_immutable); return num_immutable > 1; }
void do_moves(dungeon_t *d) { pair_t next; character *c; /* Remove the PC when it is PC turn. Replace on next call. This allows * * use to completely uninit the heap when generating a new level without * * worrying about deleting the PC. */ if (pc_is_alive(d)) { heap_insert(&d->next_turn, d->pc); } while (pc_is_alive(d) && ((c = ((character *) heap_remove_min(&d->next_turn))) != d->pc)) { if (!character_is_alive(c)) { if (d->charmap[character_get_y(c)][character_get_x(c)] == c) { d->charmap[character_get_y(c)][character_get_x(c)] = NULL; } if (c != d->pc) { character_delete(c); } continue; } character_next_turn(c); npc_next_pos(d, c, next); move_character(d, c, next); heap_insert(&d->next_turn, c); } if (pc_is_alive(d) && c == d->pc) { character_next_turn(c); if(d->objmap[character_get_y(c)][character_get_x(c)]){ if(add_to_inventory(d, d->objmap[character_get_y(c)][character_get_x(c)]) == 0){ d->objmap[character_get_y(c)][character_get_x(c)] = NULL; } } } }
static void npc_next_pos_14(dungeon *d, npc *c, pair_t next) { /* pass wall; not smart; not telepathic; tunneling; not erratic */ if (can_see(d, character_get_pos(c), character_get_pos(d->PC), 0, 0)) { c->pc_last_known_position[dim_y] = character_get_y(d->PC); c->pc_last_known_position[dim_x] = character_get_x(d->PC); npc_next_pos_line_of_sight(d, c, next); } else { npc_next_pos_rand_pass(d, c, next); } }
void pc::DoBombCombat(dungeon_t *d, character* c) { int i, j; int damage = 100; int damageSplash = (damage / 2); int dmgUsed = 0; for(i = (character_get_y(c) - 1); i <= (character_get_y(c) + 1); i++) { for(j = (character_get_x(c) - 1); j <= (character_get_x(c) + 1); j++) { if(d->charmap[i][j] && d->charmap[i][j] != d->the_pc) { if(i == character_get_y(c) && j == character_get_x(c)) { dmgUsed = damage; } else { dmgUsed = damageSplash; } io_queue_message("You hit the %s for %d.", d->charmap[i][j]->name, dmgUsed); if (dmgUsed >= d->charmap[i][j]->hp) { io_queue_message("The %s dies.", d->charmap[i][j]->name); d->charmap[i][j]->hp = 0; d->charmap[i][j]->alive = 0; d->num_monsters--; charpair(d->charmap[i][j]->position) = NULL; } else { d->charmap[i][j]->hp -= dmgUsed; } } } } }
void move_character(dungeon_t *d, character *c, pair_t next) { int rs; pair_t p; if (charpair(next) && ((next[dim_y] != character_get_y(c)) || (next[dim_x] != character_get_x(c)))) { d->combat_message = ""; rs = do_combat(d, c, charpair(next)); } /* No character in new position. */ if(rs == 0 || !charpair(next)){ d->charmap[character_get_y(c)][character_get_x(c)] = NULL; character_set_y(c, next[dim_y]); character_set_x(c, next[dim_x]); d->charmap[character_get_y(c)][character_get_x(c)] = c; } if (c == d->pc) { pc_set_speed(d, c); } }
static void npc_next_pos_11(dungeon *d, npc *c, pair_t next) { /* pass wall; smart; not telepathic; not tunneling; not erratic */ if (can_see(d, character_get_pos(c), character_get_pos(d->PC), 0, 0)) { c->pc_last_known_position[dim_y] = character_get_y(d->PC); c->pc_last_known_position[dim_x] = character_get_x(d->PC); c->have_seen_pc = 1; npc_next_pos_line_of_sight(d, c, next); } else if (c->have_seen_pc) { npc_next_pos_line_of_sight(d, c, next); } if ((next[dim_x] == c->pc_last_known_position[dim_x]) && (next[dim_y] == c->pc_last_known_position[dim_y])) { c->have_seen_pc = 0; } }
void new_dungeon(dungeon_t *d) { uint32_t sequence_number; sequence_number = d->character_sequence_number; delete_dungeon(d); init_dungeon(d); gen_dungeon(d); d->character_sequence_number = sequence_number; place_pc(d); d->charmap[character_get_y(d->pc)][character_get_x(d->pc)] = d->pc; /* Need to add a mechanism to decide on a number of monsters. --nummon * * is just for testing, and if we're generating new dungeon levels, then * * presumably we've already done that testing. We'll just put 10 in for * * now. */ gen_monsters(d, character_get_next_turn(d->pc)); gen_objects(d); }
void dijkstra(dungeon_t *d) { /* Currently assumes that monsters only move on floors. Will * * need to be modified for tunneling and pass-wall monsters. */ heap_t h; uint32_t x, y; static path_t p[DUNGEON_Y][DUNGEON_X], *c; static uint32_t initialized = 0; if (!initialized) { initialized = 1; dungeon = d; for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { p[y][x].pos[dim_y] = y; p[y][x].pos[dim_x] = x; } } } for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { d->pc_distance[y][x] = 255; } } d->pc_distance[character_get_y(d->pc)][character_get_x(d->pc)] = 0; heap_init(&h, dist_cmp, NULL); for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { if (mapxy(x, y) >= ter_floor) { p[y][x].hn = heap_insert(&h, &p[y][x]); } } } while ((c = heap_remove_min(&h))) { c->hn = NULL; if ((p[c->pos[dim_y] - 1][c->pos[dim_x] - 1].hn) && (d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] - 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] - 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] - 1][c->pos[dim_x] ].hn) && (d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] ] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] ] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] ].hn); } if ((p[c->pos[dim_y] - 1][c->pos[dim_x] + 1].hn) && (d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] + 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] + 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] + 1].hn); } if ((p[c->pos[dim_y] ][c->pos[dim_x] - 1].hn) && (d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] - 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] - 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] ][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] ][c->pos[dim_x] + 1].hn) && (d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] + 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] + 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] ][c->pos[dim_x] + 1].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] - 1].hn) && (d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] - 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] - 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] ].hn) && (d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] ] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] ] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] ].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] + 1].hn) && (d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] + 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] + 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] + 1].hn); } } heap_delete(&h); }
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; }