7 * Angband sorting algorithm -- quick sort in place
9 * Note that the details of the data we are sorting is hidden,
10 * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
11 * function hooks to interact with the data, which is given as
12 * two pointers, and which may have any user-defined form.
14 void ang_sort_aux(vptr u, vptr v, int p, int q,
15 bool(*ang_sort_comp)(vptr u, vptr v, int a, int b), void(*ang_sort_swap)(vptr u, vptr v, int a, int b))
33 while (!(*ang_sort_comp)(u, v, b, z)) b--;
36 while (!(*ang_sort_comp)(u, v, z, a)) a++;
42 (*ang_sort_swap)(u, v, a, b);
48 /* Recurse left side */
49 ang_sort_aux(u, v, p, b, ang_sort_comp, ang_sort_swap);
51 /* Recurse right side */
52 ang_sort_aux(u, v, b + 1, q, ang_sort_comp, ang_sort_swap);
57 * Angband sorting algorithm -- quick sort in place
59 * Note that the details of the data we are sorting is hidden,
60 * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
61 * function hooks to interact with the data, which is given as
62 * two pointers, and which may have any user-defined form.
64 void ang_sort(vptr u, vptr v, int n,
65 bool(*ang_sort_comp)(vptr u, vptr v, int a, int b) , void(*ang_sort_swap)(vptr u, vptr v, int a, int b))
68 ang_sort_aux(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(vptr u, vptr v, int a, int b)
80 POSITION *x = (POSITION*)(u);
81 POSITION *y = (POSITION*)(v);
83 POSITION da, db, kx, ky;
85 /* Absolute distance components */
86 kx = x[a]; kx -= p_ptr->x; kx = ABS(kx);
87 ky = y[a]; ky -= p_ptr->y; ky = ABS(ky);
89 /* Approximate Double Distance to the first point */
90 da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
92 /* Absolute distance components */
93 kx = x[b]; kx -= p_ptr->x; kx = ABS(kx);
94 ky = y[b]; ky -= p_ptr->y; ky = ABS(ky);
96 /* Approximate Double Distance to the first point */
97 db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
99 /* Compare the distances */
105 * Sorting hook -- comp function -- by importance level of grids
107 * We use "u" and "v" to point to arrays of "x" and "y" positions,
108 * and sort the arrays by level of monster
110 bool ang_sort_comp_importance(vptr u, vptr v, int a, int b)
112 POSITION *x = (POSITION*)(u);
113 POSITION *y = (POSITION*)(v);
114 grid_type *ca_ptr = ¤t_floor_ptr->grid_array[y[a]][x[a]];
115 grid_type *cb_ptr = ¤t_floor_ptr->grid_array[y[b]][x[b]];
116 monster_type *ma_ptr = ¤t_floor_ptr->m_list[ca_ptr->m_idx];
117 monster_type *mb_ptr = ¤t_floor_ptr->m_list[cb_ptr->m_idx];
118 monster_race *ap_ra_ptr, *ap_rb_ptr;
120 /* The player grid */
121 if (y[a] == p_ptr->y && x[a] == p_ptr->x) return TRUE;
122 if (y[b] == p_ptr->y && x[b] == p_ptr->x) return FALSE;
124 /* Extract monster race */
125 if (ca_ptr->m_idx && ma_ptr->ml) ap_ra_ptr = &r_info[ma_ptr->ap_r_idx];
126 else ap_ra_ptr = NULL;
127 if (cb_ptr->m_idx && mb_ptr->ml) ap_rb_ptr = &r_info[mb_ptr->ap_r_idx];
128 else ap_rb_ptr = NULL;
130 if (ap_ra_ptr && !ap_rb_ptr) return TRUE;
131 if (!ap_ra_ptr && ap_rb_ptr) return FALSE;
133 /* Compare two monsters */
134 if (ap_ra_ptr && ap_rb_ptr)
136 /* Unique monsters first */
137 if ((ap_ra_ptr->flags1 & RF1_UNIQUE) && !(ap_rb_ptr->flags1 & RF1_UNIQUE)) return TRUE;
138 if (!(ap_ra_ptr->flags1 & RF1_UNIQUE) && (ap_rb_ptr->flags1 & RF1_UNIQUE)) return FALSE;
140 /* Shadowers first (あやしい影) */
141 if ((ma_ptr->mflag2 & MFLAG2_KAGE) && !(mb_ptr->mflag2 & MFLAG2_KAGE)) return TRUE;
142 if (!(ma_ptr->mflag2 & MFLAG2_KAGE) && (mb_ptr->mflag2 & MFLAG2_KAGE)) return FALSE;
144 /* Unknown monsters first */
145 if (!ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills) return TRUE;
146 if (ap_ra_ptr->r_tkills && !ap_rb_ptr->r_tkills) return FALSE;
148 /* Higher level monsters first (if known) */
149 if (ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills)
151 if (ap_ra_ptr->level > ap_rb_ptr->level) return TRUE;
152 if (ap_ra_ptr->level < ap_rb_ptr->level) return FALSE;
155 /* Sort by index if all conditions are same */
156 if (ma_ptr->ap_r_idx > mb_ptr->ap_r_idx) return TRUE;
157 if (ma_ptr->ap_r_idx < mb_ptr->ap_r_idx) return FALSE;
160 /* An object get higher priority */
161 if (current_floor_ptr->grid_array[y[a]][x[a]].o_idx && !current_floor_ptr->grid_array[y[b]][x[b]].o_idx) return TRUE;
162 if (!current_floor_ptr->grid_array[y[a]][x[a]].o_idx && current_floor_ptr->grid_array[y[b]][x[b]].o_idx) return FALSE;
164 /* Priority from the terrain */
165 if (f_info[ca_ptr->feat].priority > f_info[cb_ptr->feat].priority) return TRUE;
166 if (f_info[ca_ptr->feat].priority < f_info[cb_ptr->feat].priority) return FALSE;
168 /* If all conditions are same, compare distance */
169 return ang_sort_comp_distance(u, v, a, b);
174 * Sorting hook -- swap function -- by "distance to player"
176 * We use "u" and "v" to point to arrays of "x" and "y" positions,
177 * and sort the arrays by distance to the player.
179 void ang_sort_swap_distance(vptr u, vptr v, int a, int b)
181 POSITION *x = (POSITION*)(u);
182 POSITION *y = (POSITION*)(v);
200 * Sorting hook -- Comp function -- see below
202 * We use "u" to point to array of monster indexes,
203 * and "v" to select the type of sorting to perform on "u".
205 bool ang_sort_art_comp(vptr u, vptr v, int a, int b)
207 u16b *who = (u16b*)(u);
208 u16b *why = (u16b*)(v);
215 /* Sort by total kills */
218 /* Extract total kills */
219 z1 = a_info[w1].tval;
220 z2 = a_info[w2].tval;
222 /* Compare total kills */
223 if (z1 < z2) return (TRUE);
224 if (z1 > z2) return (FALSE);
228 /* Sort by monster level */
232 z1 = a_info[w1].sval;
233 z2 = a_info[w2].sval;
236 if (z1 < z2) return (TRUE);
237 if (z1 > z2) return (FALSE);
241 /* Sort by monster experience */
244 /* Extract experience */
245 z1 = a_info[w1].level;
246 z2 = a_info[w2].level;
248 /* Compare experience */
249 if (z1 < z2) return (TRUE);
250 if (z1 > z2) return (FALSE);
254 /* Compare indexes */
260 * Sorting hook -- Swap function -- see below
262 * We use "u" to point to array of monster indexes,
263 * and "v" to select the type of sorting to perform.
265 void ang_sort_art_swap(vptr u, vptr v, int a, int b)
267 u16b *who = (u16b*)(u);
279 bool ang_sort_comp_quest_num(vptr u, vptr v, int a, int b)
281 QUEST_IDX *q_num = (QUEST_IDX *)u;
282 quest_type *qa = &quest[q_num[a]];
283 quest_type *qb = &quest[q_num[b]];
288 return (qa->comptime != qb->comptime) ?
289 (qa->comptime < qb->comptime) :
290 (qa->level <= qb->level);
293 void ang_sort_swap_quest_num(vptr u, vptr v, int a, int b)
295 QUEST_IDX *q_num = (QUEST_IDX *)u;
308 * @brief ペット入りモンスターボールをソートするための比較関数
309 * @param u 所持品配列の参照ポインタ
313 * @return 1の方が大であればTRUE
315 bool ang_sort_comp_pet(vptr u, vptr v, int a, int b)
317 u16b *who = (u16b*)(u);
322 monster_type *m_ptr1 = ¤t_floor_ptr->m_list[w1];
323 monster_type *m_ptr2 = ¤t_floor_ptr->m_list[w2];
324 monster_race *r_ptr1 = &r_info[m_ptr1->r_idx];
325 monster_race *r_ptr2 = &r_info[m_ptr2->r_idx];
330 if (m_ptr1->nickname && !m_ptr2->nickname) return TRUE;
331 if (m_ptr2->nickname && !m_ptr1->nickname) return FALSE;
333 if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE)) return TRUE;
334 if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE)) return FALSE;
336 if (r_ptr1->level > r_ptr2->level) return TRUE;
337 if (r_ptr2->level > r_ptr1->level) return FALSE;
339 if (m_ptr1->hp > m_ptr2->hp) return TRUE;
340 if (m_ptr2->hp > m_ptr1->hp) return FALSE;
348 * @brief モンスター種族情報を特定の基準によりソートするための比較処理
349 * Sorting hook -- Comp function -- see below
350 * @param u モンスター種族情報の入れるポインタ
352 * @param a 比較するモンスター種族のID1
353 * @param b 比較するモンスター種族のID2
354 * @return 2の方が大きければTRUEを返す
355 * We use "u" to point to array of monster indexes,
356 * and "v" to select the type of sorting to perform on "u".
358 bool ang_sort_comp_hook(vptr u, vptr v, int a, int b)
360 u16b *who = (u16b*)(u);
361 u16b *why = (u16b*)(v);
368 /* Sort by player kills */
371 /* Extract player kills */
372 z1 = r_info[w1].r_pkills;
373 z2 = r_info[w2].r_pkills;
375 /* Compare player kills */
376 if (z1 < z2) return (TRUE);
377 if (z1 > z2) return (FALSE);
381 /* Sort by total kills */
384 /* Extract total kills */
385 z1 = r_info[w1].r_tkills;
386 z2 = r_info[w2].r_tkills;
388 /* Compare total kills */
389 if (z1 < z2) return (TRUE);
390 if (z1 > z2) return (FALSE);
394 /* Sort by monster level */
398 z1 = r_info[w1].level;
399 z2 = r_info[w2].level;
402 if (z1 < z2) return (TRUE);
403 if (z1 > z2) return (FALSE);
407 /* Sort by monster experience */
410 /* Extract experience */
411 z1 = r_info[w1].mexp;
412 z2 = r_info[w2].mexp;
414 /* Compare experience */
415 if (z1 < z2) return (TRUE);
416 if (z1 > z2) return (FALSE);
420 /* Compare indexes */
426 * @brief モンスター種族情報を特定の基準によりソートするためのスワップ処理
427 * Sorting hook -- Swap function -- see below
428 * @param u モンスター種族情報の入れるポインタ
430 * @param a スワップするモンスター種族のID1
431 * @param b スワップするモンスター種族のID2
434 * We use "u" to point to array of monster indexes,
435 * and "v" to select the type of sorting to perform.
437 void ang_sort_swap_hook(vptr u, vptr v, int a, int b)
439 u16b *who = (u16b*)(u);
452 * hook function to sort monsters by level
454 bool ang_sort_comp_monster_level(vptr u, vptr v, int a, int b)
456 u16b *who = (u16b*)(u);
461 monster_race *r_ptr1 = &r_info[w1];
462 monster_race *r_ptr2 = &r_info[w2];
467 if (r_ptr2->level > r_ptr1->level) return TRUE;
468 if (r_ptr1->level > r_ptr2->level) return FALSE;
470 if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE)) return TRUE;
471 if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE)) return FALSE;
477 * @brief ペットになっているモンスターをソートするための比較処理
478 * @param u モンスターの構造体配列
480 * @param a 比較対象のモンスターID1
481 * @param b 比較対象のモンスターID2
482 * @return 2番目が大ならばTRUEを返す
484 bool ang_sort_comp_pet_dismiss(vptr u, vptr v, int a, int b)
486 u16b *who = (u16b*)(u);
491 monster_type *m_ptr1 = ¤t_floor_ptr->m_list[w1];
492 monster_type *m_ptr2 = ¤t_floor_ptr->m_list[w2];
493 monster_race *r_ptr1 = &r_info[m_ptr1->r_idx];
494 monster_race *r_ptr2 = &r_info[m_ptr2->r_idx];
499 if (w1 == p_ptr->riding) return TRUE;
500 if (w2 == p_ptr->riding) return FALSE;
502 if (m_ptr1->nickname && !m_ptr2->nickname) return TRUE;
503 if (m_ptr2->nickname && !m_ptr1->nickname) return FALSE;
505 if (!m_ptr1->parent_m_idx && m_ptr2->parent_m_idx) return TRUE;
506 if (!m_ptr2->parent_m_idx && m_ptr1->parent_m_idx) return FALSE;
508 if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE)) return TRUE;
509 if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE)) return FALSE;
511 if (r_ptr1->level > r_ptr2->level) return TRUE;
512 if (r_ptr2->level > r_ptr1->level) return FALSE;
514 if (m_ptr1->hp > m_ptr2->hp) return TRUE;
515 if (m_ptr2->hp > m_ptr1->hp) return FALSE;
522 * @brief フロア保存時のcurrent_floor_ptr->grid_array情報テンプレートをソートするための比較処理
523 * @param u current_floor_ptr->grid_arrayテンプレートの参照ポインタ
525 * @param a スワップするモンスター種族のID1
526 * @param b スワップするモンスター種族のID2
527 * @return aの方が大きければtrue
529 bool ang_sort_comp_cave_temp(vptr u, vptr v, int a, int b)
531 cave_template_type *who = (cave_template_type *)(u);
533 u16b o1 = who[a].occurrence;
534 u16b o2 = who[b].occurrence;
544 * @brief フロア保存時のcurrent_floor_ptr->grid_array情報テンプレートをソートするためのスワップ処理 / Sorting hook -- Swap function
545 * @param u current_floor_ptr->grid_arrayテンプレートの参照ポインタ
547 * @param a スワップするモンスター種族のID1
548 * @param b スワップするモンスター種族のID2
551 void ang_sort_swap_cave_temp(vptr u, vptr v, int a, int b)
553 cave_template_type *who = (cave_template_type *)(u);
555 cave_template_type holder;
568 * @brief 進化ツリーをソートするためモンスター種族の判定関数 /
569 * Sorting hook -- Comp function
572 * @param a 比較したいモンスター種族ID1
573 * @param b 比較したいモンスター種族ID2
574 * @return 2が大きければTRUEを返す
576 bool ang_sort_comp_evol_tree(vptr u, vptr v, int a, int b)
578 int **evol_tree = (int **)u;
580 int w1 = evol_tree[a][0];
581 int w2 = evol_tree[b][0];
582 monster_race *r1_ptr = &r_info[w1];
583 monster_race *r2_ptr = &r_info[w2];
588 /* Used tree first */
589 if (w1 && !w2) return TRUE;
590 if (!w1 && w2) return FALSE;
592 /* Sort by monster level */
593 if (r1_ptr->level < r2_ptr->level) return TRUE;
594 if (r1_ptr->level > r2_ptr->level) return FALSE;
596 /* Sort by monster experience */
597 if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
598 if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
600 /* Compare indexes */
605 * @brief 進化ツリーをソートするため木構造のスワップ関数 /
606 * Sorting hook -- Swap function
609 * @param a スワップしたい木構造1
610 * @param b スワップしたい木構造2
611 * @return 2が大きければTRUEを返す
613 void ang_sort_swap_evol_tree(vptr u, vptr v, int a, int b)
615 int **evol_tree = (int **)u;
622 holder = evol_tree[a];
623 evol_tree[a] = evol_tree[b];
624 evol_tree[b] = holder;