1 #include "util/sort.h"
2 #include "dungeon/quest.h"
3 #include "grid/feature.h"
5 #include "monster-race/monster-race.h"
6 #include "monster-race/race-flags1.h"
7 #include "monster/monster-flag-types.h"
8 #include "system/artifact-type-definition.h"
9 #include "system/floor-type-definition.h"
10 #include "system/grid-type-definition.h"
11 #include "system//monster-race-definition.h"
12 #include "system/monster-type-definition.h"
13 #include "system/player-type-definition.h"
16 * @brief クイックソートの実行 / Quick sort in place
17 * @param u アイテムやモンスター等への配列
18 * @param v 条件基準IDへの参照ポインタ
21 * @param ang_sort_comp 比較用の関数ポインタ
22 * @param ang_sort_swap スワップ用の関数ポインタ
24 static void exe_ang_sort(player_type *player_ptr, vptr u, vptr v, int p, int q, bool (*ang_sort_comp)(player_type *, vptr, vptr, int, int),
25 void (*ang_sort_swap)(player_type *, vptr, vptr, int, int))
35 while (!(*ang_sort_comp)(player_ptr, u, v, b, z))
39 while (!(*ang_sort_comp)(player_ptr, u, v, z, a))
45 (*ang_sort_swap)(player_ptr, u, v, a, b);
50 /* Recurse left side */
51 exe_ang_sort(player_ptr, u, v, p, b, ang_sort_comp, ang_sort_swap);
53 /* Recurse right side */
54 exe_ang_sort(player_ptr, u, v, b + 1, q, ang_sort_comp, ang_sort_swap);
58 * @brief クイックソートの受け付け / Accepting auick sort in place
59 * @param u アイテムやモンスター等への配列
60 * @param v 条件基準IDへの参照ポインタ
63 * @param ang_sort_comp 比較用の関数ポインタ
64 * @param ang_sort_swap スワップ用の関数ポインタ
66 void ang_sort(player_type *player_ptr, vptr u, vptr v, int n, bool (*ang_sort_comp)(player_type *, vptr, vptr, int, int),
67 void (*ang_sort_swap)(player_type *, vptr, vptr, int, int))
69 exe_ang_sort(player_ptr, u, v, 0, n - 1, ang_sort_comp, ang_sort_swap);
73 * Sorting hook -- comp function -- by "distance to player"
75 * We use "u" and "v" to point to arrays of "x" and "y" positions,
76 * and sort the arrays by double-distance to the player.
78 bool ang_sort_comp_distance(player_type *player_ptr, vptr u, vptr v, int a, int b)
80 POSITION *x = (POSITION *)(u);
81 POSITION *y = (POSITION *)(v);
83 /* Absolute distance components */
91 /* Approximate Double Distance to the first point */
92 POSITION da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
94 /* Absolute distance components */
102 /* Approximate Double Distance to the first point */
103 POSITION db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
105 /* Compare the distances */
110 * Sorting hook -- comp function -- by importance level of grids
112 * We use "u" and "v" to point to arrays of "x" and "y" positions,
113 * and sort the arrays by level of monster
115 bool ang_sort_comp_importance(player_type *player_ptr, vptr u, vptr v, int a, int b)
117 POSITION *x = (POSITION *)(u);
118 POSITION *y = (POSITION *)(v);
119 grid_type *ca_ptr = &player_ptr->current_floor_ptr->grid_array[y[a]][x[a]];
120 grid_type *cb_ptr = &player_ptr->current_floor_ptr->grid_array[y[b]][x[b]];
121 monster_type *ma_ptr = &player_ptr->current_floor_ptr->m_list[ca_ptr->m_idx];
122 monster_type *mb_ptr = &player_ptr->current_floor_ptr->m_list[cb_ptr->m_idx];
123 monster_race *ap_ra_ptr, *ap_rb_ptr;
125 /* The player grid */
126 if (y[a] == player_ptr->y && x[a] == player_ptr->x)
129 if (y[b] == player_ptr->y && x[b] == player_ptr->x)
132 /* Extract monster race */
133 if (ca_ptr->m_idx && ma_ptr->ml)
134 ap_ra_ptr = &r_info[ma_ptr->ap_r_idx];
138 if (cb_ptr->m_idx && mb_ptr->ml)
139 ap_rb_ptr = &r_info[mb_ptr->ap_r_idx];
143 if (ap_ra_ptr && !ap_rb_ptr)
146 if (!ap_ra_ptr && ap_rb_ptr)
149 /* Compare two monsters */
150 if (ap_ra_ptr && ap_rb_ptr) {
151 /* Unique monsters first */
152 if ((ap_ra_ptr->flags1 & RF1_UNIQUE) && !(ap_rb_ptr->flags1 & RF1_UNIQUE))
154 if (!(ap_ra_ptr->flags1 & RF1_UNIQUE) && (ap_rb_ptr->flags1 & RF1_UNIQUE))
157 /* Shadowers first (あやしい影) */
158 if (ma_ptr->mflag2.has(MFLAG2::KAGE) && mb_ptr->mflag2.has_not(MFLAG2::KAGE))
160 if (ma_ptr->mflag2.has_not(MFLAG2::KAGE) && mb_ptr->mflag2.has(MFLAG2::KAGE))
163 /* Unknown monsters first */
164 if (!ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills)
166 if (ap_ra_ptr->r_tkills && !ap_rb_ptr->r_tkills)
169 /* Higher level monsters first (if known) */
170 if (ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills) {
171 if (ap_ra_ptr->level > ap_rb_ptr->level)
173 if (ap_ra_ptr->level < ap_rb_ptr->level)
177 /* Sort by index if all conditions are same */
178 if (ma_ptr->ap_r_idx > mb_ptr->ap_r_idx)
180 if (ma_ptr->ap_r_idx < mb_ptr->ap_r_idx)
184 /* An object get higher priority */
185 if (!player_ptr->current_floor_ptr->grid_array[y[a]][x[a]].o_idx_list.empty() && player_ptr->current_floor_ptr->grid_array[y[b]][x[b]].o_idx_list.empty())
188 if (player_ptr->current_floor_ptr->grid_array[y[a]][x[a]].o_idx_list.empty() && !player_ptr->current_floor_ptr->grid_array[y[b]][x[b]].o_idx_list.empty())
191 /* Priority from the terrain */
192 if (f_info[ca_ptr->feat].priority > f_info[cb_ptr->feat].priority)
195 if (f_info[ca_ptr->feat].priority < f_info[cb_ptr->feat].priority)
198 /* If all conditions are same, compare distance */
199 return ang_sort_comp_distance(player_ptr, u, v, a, b);
203 * Sorting hook -- swap function -- by "distance to player"
205 * We use "u" and "v" to point to arrays of "x" and "y" positions,
206 * and sort the arrays by distance to the player.
208 void ang_sort_swap_position(player_type *player_ptr, vptr u, vptr v, int a, int b)
213 POSITION *x = (POSITION *)(u);
214 POSITION *y = (POSITION *)(v);
216 POSITION temp = x[a];
226 * Sorting hook -- Comp function -- see below
228 * We use "u" to point to array of monster indexes,
229 * and "v" to select the type of sorting to perform on "u".
231 bool ang_sort_art_comp(player_type *player_ptr, vptr u, vptr v, int a, int b)
236 uint16_t *who = (uint16_t *)(u);
237 uint16_t *why = (uint16_t *)(v);
244 /* Sort by total kills */
246 /* Extract total kills */
247 z1 = a_info[w1].tval;
248 z2 = a_info[w2].tval;
250 /* Compare total kills */
258 /* Sort by monster level */
261 z1 = a_info[w1].sval;
262 z2 = a_info[w2].sval;
272 /* Sort by monster experience */
274 /* Extract experience */
275 z1 = a_info[w1].level;
276 z2 = a_info[w2].level;
278 /* Compare experience */
286 /* Compare indexes */
291 * Sorting hook -- Swap function -- see below
293 * We use "u" to point to array of monster indexes,
294 * and "v" to select the type of sorting to perform.
296 void ang_sort_art_swap(player_type *player_ptr, vptr u, vptr v, int a, int b)
302 uint16_t *who = (uint16_t *)(u);
303 uint16_t holder = who[a];
308 bool ang_sort_comp_quest_num(player_type *player_ptr, vptr u, vptr v, int a, int b)
314 QUEST_IDX *q_num = (QUEST_IDX *)u;
315 quest_type *qa = &quest[q_num[a]];
316 quest_type *qb = &quest[q_num[b]];
317 return (qa->comptime != qb->comptime) ? (qa->comptime < qb->comptime) : (qa->level <= qb->level);
320 void ang_sort_swap_quest_num(player_type *player_ptr, vptr u, vptr v, int a, int b)
326 QUEST_IDX *q_num = (QUEST_IDX *)u;
327 QUEST_IDX tmp = q_num[a];
333 * @brief ペット入りモンスターボールをソートするための比較関数
334 * @param u 所持品配列の参照ポインタ
338 * @return 1の方が大であればTRUE
340 bool ang_sort_comp_pet(player_type *player_ptr, vptr u, vptr v, int a, int b)
345 uint16_t *who = (uint16_t *)(u);
350 monster_type *m_ptr1 = &player_ptr->current_floor_ptr->m_list[w1];
351 monster_type *m_ptr2 = &player_ptr->current_floor_ptr->m_list[w2];
352 monster_race *r_ptr1 = &r_info[m_ptr1->r_idx];
353 monster_race *r_ptr2 = &r_info[m_ptr2->r_idx];
355 if (m_ptr1->nickname && !m_ptr2->nickname)
358 if (m_ptr2->nickname && !m_ptr1->nickname)
361 if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE))
364 if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE))
367 if (r_ptr1->level > r_ptr2->level)
370 if (r_ptr2->level > r_ptr1->level)
373 if (m_ptr1->hp > m_ptr2->hp)
376 if (m_ptr2->hp > m_ptr1->hp)
383 * @brief モンスター種族情報を特定の基準によりソートするための比較処理
384 * Sorting hook -- Comp function -- see below
385 * @param u モンスター種族情報の入れるポインタ
387 * @param a 比較するモンスター種族のID1
388 * @param b 比較するモンスター種族のID2
389 * @return 2の方が大きければTRUEを返す
390 * We use "u" to point to array of monster indexes,
391 * and "v" to select the type of sorting to perform on "u".
393 bool ang_sort_comp_hook(player_type *player_ptr, vptr u, vptr v, int a, int b)
398 uint16_t *who = (uint16_t *)(u);
399 uint16_t *why = (uint16_t *)(v);
406 /* Sort by player kills */
408 /* Extract player kills */
409 z1 = r_info[w1].r_pkills;
410 z2 = r_info[w2].r_pkills;
412 /* Compare player kills */
419 /* Sort by total kills */
421 /* Extract total kills */
422 z1 = r_info[w1].r_tkills;
423 z2 = r_info[w2].r_tkills;
425 /* Compare total kills */
432 /* Sort by monster level */
435 z1 = r_info[w1].level;
436 z2 = r_info[w2].level;
445 /* Sort by monster experience */
447 /* Extract experience */
448 z1 = r_info[w1].mexp;
449 z2 = r_info[w2].mexp;
451 /* Compare experience */
458 /* Compare indexes */
463 * @brief モンスター種族情報を特定の基準によりソートするためのスワップ処理
464 * Sorting hook -- Swap function -- see below
465 * @param u モンスター種族情報の入れるポインタ
467 * @param a スワップするモンスター種族のID1
468 * @param b スワップするモンスター種族のID2
470 * We use "u" to point to array of monster indexes,
471 * and "v" to select the type of sorting to perform.
473 void ang_sort_swap_hook(player_type *player_ptr, vptr u, vptr v, int a, int b)
479 uint16_t *who = (uint16_t *)(u);
488 * hook function to sort monsters by level
490 bool ang_sort_comp_monster_level(player_type *player_ptr, vptr u, vptr v, int a, int b)
496 uint16_t *who = (uint16_t *)(u);
501 monster_race *r_ptr1 = &r_info[w1];
502 monster_race *r_ptr2 = &r_info[w2];
504 if (r_ptr2->level > r_ptr1->level)
507 if (r_ptr1->level > r_ptr2->level)
510 if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE))
513 if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE))
520 * @brief ペットになっているモンスターをソートするための比較処理
521 * @param u モンスターの構造体配列
523 * @param a 比較対象のモンスターID1
524 * @param b 比較対象のモンスターID2
525 * @return 2番目が大ならばTRUEを返す
527 bool ang_sort_comp_pet_dismiss(player_type *player_ptr, vptr u, vptr v, int a, int b)
532 uint16_t *who = (uint16_t *)(u);
537 monster_type *m_ptr1 = &player_ptr->current_floor_ptr->m_list[w1];
538 monster_type *m_ptr2 = &player_ptr->current_floor_ptr->m_list[w2];
539 monster_race *r_ptr1 = &r_info[m_ptr1->r_idx];
540 monster_race *r_ptr2 = &r_info[m_ptr2->r_idx];
542 if (w1 == player_ptr->riding)
545 if (w2 == player_ptr->riding)
548 if (m_ptr1->nickname && !m_ptr2->nickname)
551 if (m_ptr2->nickname && !m_ptr1->nickname)
554 if (!m_ptr1->parent_m_idx && m_ptr2->parent_m_idx)
557 if (!m_ptr2->parent_m_idx && m_ptr1->parent_m_idx)
560 if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE))
563 if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE))
566 if (r_ptr1->level > r_ptr2->level)
569 if (r_ptr2->level > r_ptr1->level)
572 if (m_ptr1->hp > m_ptr2->hp)
575 if (m_ptr2->hp > m_ptr1->hp)
582 * @brief フロア保存時のgrid情報テンプレートをソートするための比較処理
583 * @param u gridテンプレートの参照ポインタ
585 * @param a スワップするモンスター種族のID1
586 * @param b スワップするモンスター種族のID2
587 * @return aの方が大きければtrue
589 bool ang_sort_comp_cave_temp(player_type *player_ptr, vptr u, vptr v, int a, int b)
595 grid_template_type *who = (grid_template_type *)(u);
597 uint16_t o1 = who[a].occurrence;
598 uint16_t o2 = who[b].occurrence;
604 * @brief フロア保存時のgrid情報テンプレートをソートするためのスワップ処理 / Sorting hook -- Swap function
605 * @param u gridテンプレートの参照ポインタ
607 * @param a スワップするモンスター種族のID1
608 * @param b スワップするモンスター種族のID2
610 void ang_sort_swap_cave_temp(player_type *player_ptr, vptr u, vptr v, int a, int b)
616 grid_template_type *who = (grid_template_type *)(u);
617 grid_template_type holder;