/** * Walk in the given direction. */ void do_cmd_walk(struct command *cmd) { int x, y, dir; /* Don't disarm on movement if the player is trapsafe, * or the trap is disabled */ bool disarm = player->timed[TMD_TRAPSAFE] ? false : true; /* Get arguments */ if (cmd_get_direction(cmd, "direction", &dir, false) != CMD_OK) return; /* Apply confusion if necessary */ /* Confused movements use energy no matter what */ if (player_confuse_dir(player, &dir, false)) player->upkeep->energy_use = z_info->move_energy; /* Verify walkability */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; if (!do_cmd_walk_test(y, x)) return; /* Don't disarm if it's a disabled trap */ if (square_isdisabledtrap(cave, y, x)) disarm = false; player->upkeep->energy_use = z_info->move_energy; move_player(dir, disarm); }
/** * Close an open door. */ void do_cmd_close(struct command *cmd) { int y, x, dir; int err; bool more = false; /* Get arguments */ err = cmd_get_arg_direction(cmd, "direction", &dir); if (err || dir == DIR_UNKNOWN) { int y2, x2; /* Count open doors */ if (count_feats(&y2, &x2, square_isopendoor, false) == 1) { dir = coords_to_dir(y2, x2); cmd_set_arg_direction(cmd, "direction", dir); } else if (cmd_get_direction(cmd, "direction", &dir, false)) { return; } } /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Verify legality */ if (!do_cmd_close_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; } /* Monster - alert, then attack */ if (cave->squares[y][x].mon > 0) { msg("There is a monster in the way!"); py_attack(y, x); } else /* Door - close it */ more = do_cmd_close_aux(y, x); /* Cancel repeat unless told not to */ if (!more) disturb(player, 0); }
/* * Close an open door. */ void do_cmd_close(cmd_code code, cmd_arg args[]) { int y, x, dir; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Verify legality */ if (!do_cmd_close_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave->m_idx[y][x] > 0) { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Door */ else { /* Close door */ more = do_cmd_close_aux(y, x); } /* Cancel repeat unless told not to */ if (!more) disturb(p_ptr, 0, 0); }
/* * Tunnel through "walls" (including rubble and secret doors) * * Digging is very difficult without a "digger" weapon, but can be * accomplished by strong players using heavy weapons. */ void do_cmd_tunnel(cmd_code code, cmd_arg args[]) { int y, x, dir; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Oops */ if (!do_cmd_tunnel_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave->m_idx[y][x] > 0) { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Walls */ else { /* Tunnel through walls */ more = do_cmd_tunnel_aux(y, x); } /* Cancel repetition unless we can continue */ if (!more) disturb(p_ptr, 0, 0); }
/* * Walk into a trap. */ void do_cmd_jump(cmd_code code, cmd_arg args[]) { int x, y; int dir = args[0].direction; /* Apply confusion if necessary */ player_confuse_dir(p_ptr, &dir, FALSE); /* Verify walkability */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; if (!do_cmd_walk_test(y, x)) return; p_ptr->energy_use = 100; move_player(dir, FALSE); }
/* * Start running with pathfinder. * * Note that running while confused is not allowed. */ void do_cmd_pathfind(cmd_code code, cmd_arg args[]) { /* Hack XXX XXX XXX */ int dir = 5; if (player_confuse_dir(p_ptr, &dir, TRUE)) { return; } if (findpath(args[0].point.x, args[0].point.y)) { p_ptr->running = 1000; /* Calculate torch radius */ p_ptr->update |= (PU_TORCH); p_ptr->running_withpathfind = TRUE; run_step(0); } }
/** * Fire an object from the quiver, pack or floor at a target. */ void do_cmd_fire(struct command *cmd) { int dir; int range = MIN(6 + 2 * player->state.ammo_mult, z_info->max_range); int shots = player->state.num_shots; ranged_attack attack = make_ranged_shot; struct object *bow = equipped_item_by_slot_name(player, "shooting"); struct object *obj; /* Get arguments */ if (cmd_get_item(cmd, "item", &obj, /* Prompt */ "Fire which ammunition?", /* Error */ "You have no ammunition to fire.", /* Filter */ obj_can_fire, /* Choice */ USE_INVEN | USE_QUIVER | USE_FLOOR | QUIVER_TAGS) != CMD_OK) return; if (cmd_get_target(cmd, "target", &dir) == CMD_OK) player_confuse_dir(player, &dir, FALSE); else return; /* Require a usable launcher */ if (!bow || !player->state.ammo_tval) { msg("You have nothing to fire with."); return; } /* Check the item being fired is usable by the player. */ if (!item_is_available(obj, NULL, USE_QUIVER | USE_INVEN | USE_FLOOR)) { msg("That item is not within your reach."); return; } /* Check the ammo can be used with the launcher */ if (obj->tval != player->state.ammo_tval) { msg("That ammo cannot be fired by your current weapon."); return; } ranged_helper(obj, dir, range, shots, attack); }
/* * Start running. * * Note that running while confused is not allowed. */ void do_cmd_run(cmd_code code, cmd_arg args[]) { int x, y; int dir = args[0].direction; if (player_confuse_dir(p_ptr, &dir, TRUE)) { return; } /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; if (!do_cmd_walk_test(y, x)) return; /* Start run */ run_step(dir); }
/* * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter_aux(int dir) { int y, x; bool more = FALSE; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Attack monsters */ if (cave->m_idx[y][x] > 0) py_attack(y, x); /* Tunnel through walls and rubble */ else if (cave_isdiggable(cave, y, x)) more = do_cmd_tunnel_aux(y, x); /* Open closed doors */ else if (cave_iscloseddoor(cave, y, x)) more = do_cmd_open_aux(y, x); /* Disarm traps */ else if (cave_isknowntrap(cave, y, x)) more = do_cmd_disarm_aux(y, x); /* Oops */ else msg("You spin around."); /* Cancel repetition unless we can continue */ if (!more) disturb(p_ptr, 0, 0); }
/** * Tunnel through "walls" (including rubble and doors, secret or otherwise) * * Digging is very difficult without a "digger" weapon, but can be * accomplished by strong players using heavy weapons. */ void do_cmd_tunnel(struct command *cmd) { int y, x, dir; bool more = false; /* Get arguments */ if (cmd_get_direction(cmd, "direction", &dir, false)) return; /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Oops */ if (!do_cmd_tunnel_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; } /* Attack any monster we run into */ if (cave->squares[y][x].mon > 0) { msg("There is a monster in the way!"); py_attack(y, x); } else { /* Tunnel through walls */ more = do_cmd_tunnel_aux(y, x); } /* Cancel repetition unless we can continue */ if (!more) disturb(player, 0); }
/* * Walk in the given direction. */ void do_cmd_walk(cmd_code code, cmd_arg args[]) { int x, y; int dir = args[0].direction; /* Apply confusion if necessary */ player_confuse_dir(p_ptr, &dir); /* Confused movements use energy no matter what */ if (dir != args[0].direction) p_ptr->energy_use = 100; /* Verify walkability */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; if (!do_cmd_walk_test(y, x)) return; p_ptr->energy_use = 100; move_player(dir, TRUE); }
/** * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter_aux(int dir) { int y, x; bool more = false; /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; } /* Action depends on what's there */ if (cave->squares[y][x].mon > 0) /* Attack monsters */ py_attack(y, x); else if (square_isdiggable(cave, y, x)) /* Tunnel through walls and rubble */ more = do_cmd_tunnel_aux(y, x); else if (square_iscloseddoor(cave, y, x)) /* Open closed doors */ more = do_cmd_open_aux(y, x); else if (square_isknowntrap(cave, y, x)) /* Disarm traps */ more = do_cmd_disarm_aux(y, x); else /* Oops */ msg("You spin around."); /* Cancel repetition unless we can continue */ if (!more) disturb(player, 0); }
/** * Start running. * * Note that running while confused is not allowed. */ void do_cmd_run(struct command *cmd) { int x, y, dir; /* Get arguments */ if (cmd_get_direction(cmd, "direction", &dir, false) != CMD_OK) return; if (player_confuse_dir(player, &dir, true)) return; /* Get location */ if (dir) { y = player->py + ddy[dir]; x = player->px + ddx[dir]; if (!do_cmd_walk_test(y, x)) return; } /* Start run */ run_step(dir); }
/** * Walk into a trap. */ void do_cmd_jump(struct command *cmd) { int x, y, dir; /* Get arguments */ if (cmd_get_direction(cmd, "direction", &dir, false) != CMD_OK) return; /* Apply confusion if necessary */ if (player_confuse_dir(player, &dir, false)) player->upkeep->energy_use = z_info->move_energy; /* Verify walkability */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; if (!do_cmd_walk_test(y, x)) return; player->upkeep->energy_use = z_info->move_energy; move_player(dir, false); }
/** * Throw an object from the quiver, pack or floor. */ void do_cmd_throw(struct command *cmd) { int dir; int shots = 1; int str = adj_str_blow[player->state.stat_ind[STAT_STR]]; ranged_attack attack = make_ranged_throw; int weight; int range; struct object *obj; /* Get arguments */ if (cmd_get_item(cmd, "item", &obj, /* Prompt */ "Throw which item?", /* Error */ "You have nothing to throw.", /* Filter */ NULL, /* Choice */ USE_QUIVER | USE_INVEN | USE_FLOOR | QUIVER_TAGS) != CMD_OK) return; if (cmd_get_target(cmd, "target", &dir) == CMD_OK) player_confuse_dir(player, &dir, FALSE); else return; weight = MAX(obj->weight, 10); range = MIN(((str + 20) * 10) / weight, 10); /* Make sure the player isn't throwing wielded items */ if (object_is_equipped(player->body, obj)) { msg("You have cannot throw wielded items."); return; } ranged_helper(obj, dir, range, shots, attack); }
/* * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter_aux(int dir) { int y, x; int feat; bool more = FALSE; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Original feature */ feat = cave->feat[y][x]; /* Must have knowledge to know feature XXX XXX */ if (!(cave->info[y][x] & (CAVE_MARK))) feat = FEAT_NONE; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Attack monsters */ if (cave->m_idx[y][x] > 0) { py_attack(y, x); } /* Tunnel through walls */ else if (feat >= FEAT_SECRET) { more = do_cmd_tunnel_aux(y, x); } #if 0 /* Bash jammed doors */ else if (feat >= FEAT_DOOR_HEAD + 0x08) { more = do_cmd_bash_aux(y, x); } #endif /* Open closed doors */ else if (feat >= FEAT_DOOR_HEAD) { more = do_cmd_open_aux(y, x); } /* Disarm traps */ else if (feat >= FEAT_TRAP_HEAD) { more = do_cmd_disarm_aux(y, x); } #if 0 /* Close open doors */ else if (feat == FEAT_OPEN) { more = do_cmd_close_aux(y, x); } #endif /* Oops */ else { msg("You spin around."); } /* Cancel repetition unless we can continue */ if (!more) disturb(0, 0); }
/** * Disarms a trap, or a chest * * Traps must be visible, chests must be known trapped */ void do_cmd_disarm(struct command *cmd) { int y, x, dir; int err; struct object *obj; bool more = false; /* Get arguments */ err = cmd_get_arg_direction(cmd, "direction", &dir); if (err || dir == DIR_UNKNOWN) { int y2, x2; int n_traps, n_chests; n_traps = count_feats(&y2, &x2, square_isknowntrap, true); n_chests = count_chests(&y2, &x2, CHEST_TRAPPED); if (n_traps + n_chests == 1) { dir = coords_to_dir(y2, x2); cmd_set_arg_direction(cmd, "direction", dir); } else if (cmd_get_direction(cmd, "direction", &dir, n_chests > 0)) { /* If there are chests to disarm, 5 is allowed as a direction */ return; } } /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chests */ obj = chest_check(y, x, CHEST_TRAPPED); /* Verify legality */ if (!obj && !do_cmd_disarm_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chests */ obj = chest_check(y, x, CHEST_TRAPPED); } /* Monster */ if (cave->squares[y][x].mon > 0) { msg("There is a monster in the way!"); py_attack(y, x); } else if (obj) /* Chest */ more = do_cmd_disarm_chest(y, x, obj); else if (square_iscloseddoor(cave, y, x) && !square_islockeddoor(cave, y, x)) /* Door to lock */ more = do_cmd_lock_door(y, x); else /* Disarm trap */ more = do_cmd_disarm_aux(y, x); /* Cancel repeat unless told not to */ if (!more) disturb(player, 0); }
/* * Open a closed/locked/jammed door or a closed/locked chest. * * Unlocking a locked door/chest is worth one experience point. */ void do_cmd_open(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_open_test(y, x)) { /* Cancel repeat */ disturb(0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chest */ o_idx = chest_check(y, x); } /* Monster */ if (cave->m_idx[y][x] > 0) { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Chest */ else if (o_idx) { /* Open the chest */ more = do_cmd_open_chest(y, x, o_idx); } /* Door */ else { /* Open the door */ more = do_cmd_open_aux(y, x); } /* Cancel repeat unless we may continue */ if (!more) disturb(0, 0); }
/** * Open a closed/locked/jammed door or a closed/locked chest. * * Unlocking a locked chest is worth one experience point; since doors are * player lockable, there is no experience for unlocking doors. */ void do_cmd_open(struct command *cmd) { int y, x, dir; struct object *obj; bool more = false; int err; struct monster *m; /* Get arguments */ err = cmd_get_arg_direction(cmd, "direction", &dir); if (err || dir == DIR_UNKNOWN) { int y2, x2; int n_closed_doors, n_locked_chests; n_closed_doors = count_feats(&y2, &x2, square_iscloseddoor, false); n_locked_chests = count_chests(&y2, &x2, CHEST_OPENABLE); if (n_closed_doors + n_locked_chests == 1) { dir = coords_to_dir(y2, x2); cmd_set_arg_direction(cmd, "direction", dir); } else if (cmd_get_direction(cmd, "direction", &dir, false)) { return; } } /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chest */ obj = chest_check(y, x, CHEST_OPENABLE); /* Check for door */ if (!obj && !do_cmd_open_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chest */ obj = chest_check(y, x, CHEST_OPENABLE); } /* Monster */ m = square_monster(cave, y, x); if (m) { /* Mimics surprise the player */ if (is_mimicking(m)) { become_aware(m); /* Mimic wakes up */ mon_clear_timed(m, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false); } else { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } else if (obj) { /* Chest */ more = do_cmd_open_chest(y, x, obj); } else { /* Door */ more = do_cmd_open_aux(y, x); } /* Cancel repeat unless we may continue */ if (!more) disturb(player, 0); }
/* * Disarms a trap, or a chest */ void do_cmd_disarm(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_disarm_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); } /* Monster */ if (cave->m_idx[y][x] > 0) { msg("There is a monster in the way!"); py_attack(y, x); } /* Chest */ else if (o_idx) more = do_cmd_disarm_chest(y, x, o_idx); /* Door to lock */ else if (cave->feat[y][x] == FEAT_DOOR_HEAD) more = do_cmd_lock_door(y, x); /* Disarm trap */ else more = do_cmd_disarm_aux(y, x); /* Cancel repeat unless told not to */ if (!more) disturb(p_ptr, 0, 0); }
/* * Jam a closed door with a spike * * This command may NOT be repeated */ void do_cmd_spike(cmd_code code, cmd_arg args[]) { int y, x, dir, item = 0; dir = args[0].direction; /* Get a spike */ if (!get_spike(&item)) { /* Message */ msg("You have no spikes!"); /* Done */ return; } /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Verify legality */ if (!do_cmd_spike_test(y, x)) return; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave->m_idx[y][x] > 0) { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Go for it */ else { /* Verify legality */ if (!do_cmd_spike_test(y, x)) return; /* Successful jamming */ msg("You jam the door with a spike."); /* Convert "locked" to "stuck" XXX XXX XXX */ if (cave->feat[y][x] < FEAT_DOOR_HEAD + 0x08) cave->feat[y][x] += 0x08; /* Add one spike to the door */ if (cave->feat[y][x] < FEAT_DOOR_TAIL) cave->feat[y][x] += 0x01; /* Use up, and describe, a single spike, from the bottom */ inven_item_increase(item, -1); inven_item_describe(item); inven_item_optimize(item); } }
/* * Open a closed/locked/jammed door or a closed/locked chest. * * Unlocking a locked door/chest is worth one experience point. */ void do_cmd_open(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_open_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chest */ o_idx = chest_check(y, x); } /* Monster */ if (cave->m_idx[y][x] > 0) { int m_idx = cave->m_idx[y][x]; /* Mimics surprise the player */ if (is_mimicking(m_idx)) { become_aware(m_idx); /* Mimic wakes up */ mon_clear_timed(m_idx, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE); } else { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } /* Chest */ else if (o_idx) { /* Open the chest */ more = do_cmd_open_chest(y, x, o_idx); } /* Door */ else { /* Open the door */ more = do_cmd_open_aux(y, x); } /* Cancel repeat unless we may continue */ if (!more) disturb(p_ptr, 0, 0); }