1 /*
2 * Support for the "party" system.
3 */
4
5 #include "mangband.h"
6
7 /*
8 * Lookup a party number by name.
9 */
party_lookup(cptr name)10 int party_lookup(cptr name)
11 {
12 int i;
13
14 /* Check each party */
15 for (i = 0; i < MAX_PARTIES; i++)
16 {
17 /* Check name */
18 if (streq(parties[i].name, name))
19 return i;
20 }
21
22 /* No match */
23 return -1;
24 }
25
26 /*
27 * Check for the existance of a player in a party.
28 */
player_in_party(int party_id,player_type * p_ptr)29 bool player_in_party(int party_id, player_type *p_ptr)
30 {
31 /* Check */
32 if (p_ptr->party == party_id)
33 return TRUE;
34
35 /* Not in the party */
36 return FALSE;
37 }
38
39 /*
40 * Create a new party, owned by "p_ptr", and called
41 * "name".
42 */
party_create(player_type * p_ptr,cptr name)43 int party_create(player_type *p_ptr, cptr name)
44 {
45 int index = 0, i;
46 hturn oldest = turn;
47
48 /* Check for already existing party by that name */
49 if (party_lookup(name) != -1)
50 {
51 msg_print(p_ptr, "A party by that name already exists.");
52 return FALSE;
53 }
54
55 /* Make sure this guy isn't in some other party already */
56 if (p_ptr->party != 0)
57 {
58 msg_print(p_ptr, "You already belong to a party!");
59 return FALSE;
60 }
61
62 /* Find the "best" party index */
63 for (i = 1; i < MAX_PARTIES; i++)
64 {
65 /* Check deletion time of disbanded parties */
66 if (parties[i].num == 0 && ht_passed(&oldest, &parties[i].created, 0))
67 {
68 /* Track oldest */
69 oldest = parties[i].created;
70 index = i;
71 }
72 }
73
74 /* Make sure we found an empty slot */
75 if (index == 0 || ht_eq(&oldest, &turn))
76 {
77 /* Error */
78 msg_print(p_ptr, "There aren't enough party slots!");
79 return FALSE;
80 }
81
82 /* Set party name */
83 strcpy(parties[index].name, name);
84
85 /* Set owner name */
86 strcpy(parties[index].owner, p_ptr->name);
87
88 /* Add the owner as a member */
89 p_ptr->party = index;
90 parties[index].num++;
91
92 /* Set the "creation time" */
93 parties[index].created = turn;
94
95 /* Resend party info */
96 send_party_info(p_ptr);
97
98 /* Success */
99 return TRUE;
100 }
101
102 /*
103 * Add a player to a party.
104 */
party_add(player_type * q_ptr,cptr name)105 int party_add(player_type *q_ptr, cptr name)
106 {
107 player_type *p_ptr = NULL;
108 int party_id = q_ptr->party, i;
109
110 /* Find name */
111 for (i = 1; i <= NumPlayers; i++)
112 {
113 /* Check this one */
114 if (streq(name, Players[i]->name))
115 {
116 /* Found him */
117 p_ptr = Players[i];
118 break;
119 }
120 }
121
122 /* Check for existance */
123 if (p_ptr == NULL)
124 {
125 /* Oops */
126 msg_print(q_ptr, "That player is not currently in the game.");
127
128 return FALSE;
129 }
130
131 /* Check for hostility */
132 if (check_hostile(p_ptr, q_ptr))
133 {
134 msg_print(q_ptr, "That player is hostile towards you.");
135 return FALSE;
136 }
137
138 if (check_hostile(q_ptr, p_ptr))
139 {
140 msg_print(q_ptr, "You are hostile to that player.");
141 return FALSE;
142 }
143
144 /* Make sure this isn't an imposter */
145 if (!streq(parties[party_id].owner, q_ptr->name))
146 {
147 /* Message */
148 msg_print(q_ptr, "You must be the owner to add someone.");
149
150 /* Abort */
151 return FALSE;
152 }
153
154 /* Make sure this added person is neutral */
155 if (p_ptr->party != 0)
156 {
157 /* Message */
158 msg_print(q_ptr, "That player is already in a party.");
159
160 /* Abort */
161 return FALSE;
162 }
163
164 /* Tell the party about its new member */
165 party_msg_format(party_id, "%s has been added to party %s.", p_ptr->name, parties[party_id].name);
166
167 /* One more player in this party */
168 parties[party_id].num++;
169
170 /* Tell him about it */
171 msg_format(p_ptr, "You've been added to party '%s'.", parties[party_id].name);
172
173 /* Set his party number */
174 p_ptr->party = party_id;
175
176 /* Resend info */
177 send_party_info(p_ptr);
178
179 /* Success */
180 return TRUE;
181 }
182
183 /*
184 * Remove a person from a party.
185 *
186 * Removing the party owner destroys the party.
187 */
party_remove(player_type * q_ptr,cptr name)188 int party_remove(player_type *q_ptr, cptr name)
189 {
190 player_type *p_ptr = NULL;
191 int party_id = q_ptr->party, i;
192
193 /* Find name */
194 for (i = 1; i <= NumPlayers; i++)
195 {
196 /* Check this one */
197 if (streq(name, Players[i]->name))
198 {
199 /* Found him */
200 p_ptr = Players[i];
201 break;
202 }
203 }
204
205 /* Check for existance */
206 if (p_ptr == NULL)
207 {
208 /* Oops */
209 msg_print(q_ptr, "That player is not currently in the game.");
210
211 return FALSE;
212 }
213
214 /* Make sure this is the owner */
215 if (!streq(parties[party_id].owner, q_ptr->name))
216 {
217 /* Message */
218 msg_print(q_ptr, "You must be the owner to delete someone.");
219
220 /* Abort */
221 return FALSE;
222 }
223
224 /* Make sure they were in the party to begin with */
225 if (!player_in_party(party_id, p_ptr))
226 {
227 /* Message */
228 msg_print(q_ptr, "You can only delete party members.");
229
230 /* Abort */
231 return FALSE;
232 }
233
234 /* See if this is the owner we're deleting */
235 if (same_player(q_ptr, p_ptr))
236 {
237 /* Remove the party altogether */
238
239 /* Set the number of people in this party to zero */
240 parties[party_id].num = 0;
241
242 /* Remove everyone else */
243 for (i = 1; i <= NumPlayers; i++)
244 {
245 /* Check if they are in here */
246 if (player_in_party(party_id, Players[i]))
247 {
248 Players[i]->party = 0;
249 msg_print(Players[i], "Your party has been disbanded.");
250 send_party_info(Players[i]);
251 }
252 }
253
254 /* Set the creation time to "disbanded time" */
255 parties[party_id].created = turn;
256
257 /* Empty the name */
258 strcpy(parties[party_id].name, "");
259 }
260
261 /* Keep the party, just lose a member */
262 else
263 {
264 /* Lose a member */
265 parties[party_id].num--;
266
267 /* Set his party number back to "neutral" */
268 p_ptr->party = 0;
269
270 /* Messages */
271 msg_print(p_ptr, "You have been removed from your party.");
272 party_msg_format(party_id, "%s has been removed from the party.", p_ptr->name);
273
274 /* Resend info */
275 send_party_info(p_ptr);
276 }
277
278 return TRUE;
279 }
280
281
282 /*
283 * A player wants to leave a party.
284 */
party_leave(player_type * p_ptr)285 void party_leave(player_type *p_ptr)
286 {
287 int party_id = p_ptr->party;
288
289 /* Make sure he belongs to a party */
290 if (!party_id)
291 {
292 msg_print(p_ptr, "You don't belong to a party.");
293 return;
294 }
295
296 /* If he's the owner, use the other function */
297 if (streq(p_ptr->name, parties[party_id].owner))
298 {
299 /* Call party_remove */
300 party_remove(p_ptr, p_ptr->name);
301 return;
302 }
303
304 /* Lose a member */
305 parties[party_id].num--;
306
307 /* Set him back to "neutral" */
308 p_ptr->party = 0;
309
310 /* Inform people */
311 msg_print(p_ptr, "You have been removed from your party.");
312 party_msg_format(party_id, "%s has left the party.", p_ptr->name);
313
314 /* Resend info */
315 send_party_info(p_ptr);
316 }
317
318
319 /*
320 * Send a message to everyone in a party.
321 */
party_msg(int party_id,cptr msg)322 void party_msg(int party_id, cptr msg)
323 {
324 int i;
325
326 /* Check for this guy */
327 for (i = 1; i <= NumPlayers; i++)
328 {
329 /* Check this guy */
330 if (player_in_party(party_id, Players[i]))
331 msg_print_aux(Players[i], msg, MSG_WHISPER);
332 }
333 }
334
335 /*
336 * Send a formatted message to a party.
337 */
party_msg_format(int party_id,cptr fmt,...)338 void party_msg_format(int party_id, cptr fmt, ...)
339 {
340 va_list vp;
341 char buf[1024];
342
343 /* Begin the Varargs Stuff */
344 va_start(vp, fmt);
345
346 /* Format the args, save the length */
347 (void)vstrnfmt(buf, 1024, fmt, vp);
348
349 /* End the Varargs Stuff */
350 va_end(vp);
351
352 /* Display */
353 party_msg(party_id, buf);
354 }
355
356 /* Message nearby party members */
party_msg_format_near(player_type * p_ptr,u16b type,cptr fmt,...)357 void party_msg_format_near(player_type *p_ptr, u16b type, cptr fmt, ...)
358 {
359 player_type *q_ptr; /* Player who does the messaging */
360 va_list vp;
361 char buf[1024];
362 int i;
363 int Depth = p_ptr->dun_depth;
364 int y = p_ptr->py;
365 int x = p_ptr->px;
366 int party = p_ptr->party;
367
368 /* Remember who started this */
369 q_ptr = p_ptr;
370
371 /* Not a member of any party */
372 if (!party) return;
373
374 /* Begin the Varargs Stuff */
375 va_start(vp, fmt);
376
377 /* Format the args, save the length */
378 (void)vstrnfmt(buf, 1024, fmt, vp);
379
380 /* End the Varargs Stuff */
381 va_end(vp);
382
383 /* Display */
384 for (i = 1; i <= NumPlayers; i++)
385 {
386 /* Check this player */
387 p_ptr = Players[i];
388
389 /* Don't send the message to the player who caused it */
390 if (same_player(q_ptr, p_ptr)) continue;
391
392 /* Make sure this player is at this depth */
393 if (p_ptr->dun_depth != Depth) continue;
394
395 /* Meh, different party */
396 if (!player_in_party(party, p_ptr)) continue;
397
398 /* Can he see this player? */
399 if (p_ptr->cave_flag[y][x] & CAVE_VIEW)
400 {
401 /* Send the message */
402 msg_print_aux(p_ptr, buf, type);
403 }
404 }
405 }
406
407
408 /*
409 * Split some experience among party members.
410 *
411 * This should ONLY be used while killing monsters. The amount
412 * should be the monster base experience times the monster level.
413 *
414 * This algorithm may need some work.... However, it does have some nifty
415 * features, such as:
416 *
417 * 1) A party with just one member functions identically as before.
418 *
419 * 2) A party with two equally-levelled members functions such that each
420 * member gets half as much experience as he would have by killing the monster
421 * by himself.
422 *
423 * 3) Higher-leveled members of a party get higher percentages of the
424 * experience.
425 */
426
427 /* The XP distribution was too unfair for low level characters,
428 it made partying a real pain. I am changing it so that if the players
429 have a difference in level of less than 5 than there is no difference
430 in XP distribution.
431
432 I am also changing it so it divides by each players level, AFTER
433 it has been given to them.
434
435 UPDATE: it appears that it may be giving too much XP to the low lvl chars,
436 but I have been too lazy to change it... however, this doesnt appear to be being
437 abused much, and the new system is regardless much nicer than the old one.
438
439 -APD-
440 */
441
party_gain_exp(player_type * q_ptr,int party_id,s32b amount,int m_idx)442 void party_gain_exp(player_type *q_ptr, int party_id, s32b amount, int m_idx)
443 {
444 int i, Depth = q_ptr->dun_depth;
445 s32b new_exp, new_exp_frac, average_lev = 0, num_members = 0;
446 s32b modified_level;
447
448 /* Mark needed people */
449 num_members = party_mark_members(q_ptr, m_idx);
450
451 /* Calculate the average level */
452 for (i = 1; i <= NumPlayers; i++)
453 {
454 player_type *p_ptr = Players[i];
455 if (p_ptr->in_hack)
456 {
457 /* Increase the "divisor" */
458 average_lev += p_ptr->lev;
459 num_members++;
460 }
461 }
462
463 /* Now, distribute the experience */
464 for (i = 1; i <= NumPlayers; i++)
465 {
466 player_type *p_ptr = Players[i];
467
468 /* Check for his involvment */
469 if (p_ptr->in_hack)
470 {
471 /* Calculate this guy's experience */
472
473 if (p_ptr->lev * num_members < average_lev) // below average
474 {
475 if ((average_lev - p_ptr->lev * num_members) > 2 * num_members )
476 {
477 modified_level = p_ptr->lev * num_members + 2 * num_members;
478 }
479 else modified_level = average_lev;
480 }
481 else
482 {
483 if ((p_ptr->lev * num_members - average_lev) > 2 * num_members )
484 {
485 modified_level = p_ptr->lev * num_members - 2 * num_members;
486 }
487 else modified_level = average_lev;
488
489 }
490
491
492 new_exp = (amount * modified_level) / (average_lev * num_members * p_ptr->lev);
493 new_exp_frac = ((((amount * modified_level) % (average_lev * num_members * p_ptr->lev) )
494 * 0x10000L ) / (average_lev * num_members * p_ptr->lev)) + p_ptr->exp_frac;
495
496 /* Keep track of experience */
497 if (new_exp_frac >= 0x10000L)
498 {
499 new_exp++;
500 p_ptr->exp_frac = new_exp_frac - 0x10000L;
501 }
502 else
503 {
504 p_ptr->exp_frac = new_exp_frac;
505 }
506
507 /* Gain experience */
508 gain_exp(p_ptr, new_exp);
509 }
510 }
511 }
party_mark_members(player_type * p_ptr,int m_idx)512 int party_mark_members(player_type *p_ptr, int m_idx)
513 {
514 player_type *q_ptr;
515 int i, total = 0;
516
517 /* Determine players involved in killing */
518 for (i = 1; i <= NumPlayers; i++)
519 {
520 q_ptr = Players[i];
521 q_ptr->in_hack = FALSE;
522 if (same_player(q_ptr, p_ptr) || ((p_ptr->party) &&
523 (!m_idx || q_ptr->mon_hrt[m_idx]) &&
524 (q_ptr->dun_depth == p_ptr->dun_depth) &&
525 (q_ptr->party == p_ptr->party) &&
526 ((cfg_party_sharelevel == -1) || (abs(q_ptr->lev - p_ptr->lev) <= cfg_party_sharelevel))
527 ))
528 {
529 q_ptr->in_hack = TRUE;
530 total++;
531 }
532 }
533
534 return total;
535 }
party_share_hurt(player_type * p_ptr,player_type * q_ptr)536 void party_share_hurt(player_type *p_ptr, player_type *q_ptr)
537 {
538 int i;
539
540 /* Not in party, or not the same party */
541 if (!p_ptr->party || p_ptr->party != q_ptr->party)
542 return;
543
544 /* Copy hurt */
545 for (i = 0; i < MAX_M_IDX; i++)
546 {
547 if (q_ptr->mon_hrt[i])
548 p_ptr->mon_hrt[i] = TRUE;
549 }
550 }
551
552 /*
553 * Add a player to another player's list of hostilities.
554 */
add_hostility(player_type * p_ptr,cptr name)555 bool add_hostility(player_type *p_ptr, cptr name)
556 {
557 player_type *q_ptr;
558 hostile_type *h_ptr;
559 int i;
560
561 /* Check if PvP is possible at all */
562 if (cfg_pvp_hostility > 2)
563 {
564 /* Message */
565 msg_print(p_ptr, "You cannot be hostile.");
566
567 return FALSE;
568 }
569
570 /* Check for sillyness */
571 if (streq(name, p_ptr->name))
572 {
573 /* Message */
574 msg_print(p_ptr, "You cannot be hostile toward yourself.");
575
576 return FALSE;
577 }
578
579 /* Search for player to add */
580 for (i = 1; i <= NumPlayers; i++)
581 {
582 q_ptr = Players[i];
583
584 /* Check name */
585 if (!streq(q_ptr->name, name)) continue;
586
587 /* Make sure players aren't in the same party */
588 if (p_ptr->party && player_in_party(p_ptr->party, q_ptr))
589 {
590 /* Message */
591 msg_format(p_ptr, "%^s is in your party!", q_ptr->name);
592
593 return FALSE;
594 }
595
596 /* Ensure we don't add the same player twice */
597 for (h_ptr = p_ptr->hostile; h_ptr; h_ptr = h_ptr->next)
598 {
599 /* Check this ID */
600 if (h_ptr->id == q_ptr->id)
601 {
602 /* Message */
603 msg_format(p_ptr, "You are already hostile toward %s.", q_ptr->name);
604
605 return FALSE;
606 }
607 }
608
609 /* Create a new hostility node */
610 MAKE(h_ptr, hostile_type);
611
612 /* Set ID in node */
613 h_ptr->id = q_ptr->id;
614
615 /* Put this node at the beginning of the list */
616 h_ptr->next = p_ptr->hostile;
617 p_ptr->hostile = h_ptr;
618
619 /* Message */
620 msg_format(p_ptr, "You are now hostile toward %s.", q_ptr->name);
621
622 /* Notify the victim */
623 if (cfg_pvp_notify) msg_format(q_ptr, "%s is now hostile towards you.", p_ptr->name);
624
625 /* Success */
626 return TRUE;
627 }
628 #if 0
629 /* Search for party to add */
630 if ((i = party_lookup(name)) != -1)
631 {
632 /* Ensure we don't add the same party twice */
633 for (h_ptr = p_ptr->hostile; h_ptr; h_ptr = h_ptr->next)
634 {
635 /* Check this ID */
636 if (h_ptr->id == 0 - i)
637 {
638 /* Message */
639 msg_format(p_ptr, "You are already hostile toward party '%s'.", parties[i].name);
640
641 return FALSE;
642 }
643 }
644
645 /* Create a new hostility node */
646 MAKE(h_ptr, hostile_type);
647
648 /* Set ID in node */
649 h_ptr->id = 0 - i;
650
651 /* Put this node at the beginning of the list */
652 h_ptr->next = p_ptr->hostile;
653 p_ptr->hostile = h_ptr;
654
655 /* Message */
656 msg_format(p_ptr, "You are now hostile toward party '%s'.", parties[i].name);
657
658 /* Success */
659 return TRUE;
660 }
661 #endif
662 /* Couldn't find player */
663 msg_format(p_ptr, "%^s is not currently in the game.", name);
664
665 return FALSE;
666 }
667
668 /*
669 * Remove an entry from a player's list of hostilities
670 */
remove_hostility(player_type * p_ptr,cptr name)671 bool remove_hostility(player_type *p_ptr, cptr name)
672 {
673 hostile_type *h_ptr, *i_ptr;
674 cptr p;
675
676 /* Initialize lock-step */
677 i_ptr = NULL;
678
679 /* Search entries */
680 for (h_ptr = p_ptr->hostile; h_ptr; i_ptr = h_ptr, h_ptr = h_ptr->next)
681 {
682 /* Lookup name of this entry */
683 if (h_ptr->id > 0)
684 {
685 /* Look up name */
686 p = lookup_player_name(h_ptr->id);
687
688 /* Check player name */
689 if (p && streq(p, name))
690 {
691 /* Delete this entry */
692 if (i_ptr)
693 {
694 /* Skip over */
695 i_ptr->next = h_ptr->next;
696 }
697 else
698 {
699 /* Adjust beginning of list */
700 p_ptr->hostile = h_ptr->next;
701 }
702
703 /* Message */
704 msg_format(p_ptr, "No longer hostile toward %s.", name);
705
706 /* Delete node */
707 KILL(h_ptr);
708
709 /* Success */
710 return TRUE;
711 }
712 }
713 #if 0
714 else
715 {
716 /* Assume this is a party */
717 if (streq(parties[0 - h_ptr->id].name, name))
718 {
719 /* Delete this entry */
720 if (i_ptr)
721 {
722 /* Skip over */
723 i_ptr->next = h_ptr->next;
724 }
725 else
726 {
727 /* Adjust beginning of list */
728 p_ptr->hostile = h_ptr->next;
729 }
730
731 /* Message */
732 msg_format(p_ptr, "No longer hostile toward party '%s'.", name);
733
734 /* Delete node */
735 KILL(h_ptr, hostile_type);
736
737 /* Success */
738 return TRUE;
739 }
740 }
741 #endif
742 }
743
744 /* Message */
745 msg_format(p_ptr, "You are not hostile toward %s.", name);
746
747 /* Failure */
748 return FALSE;
749 }
750
751 /*
752 * Check if player "p_ptr" is hostile toward player "q_ptr"
753 */
check_hostile(player_type * p_ptr,player_type * q_ptr)754 bool check_hostile(player_type *p_ptr, player_type *q_ptr)
755 {
756 hostile_type *h_ptr;
757
758 /* Scan list */
759 for (h_ptr = p_ptr->hostile; h_ptr; h_ptr = h_ptr->next)
760 {
761 /* Check ID */
762 if (h_ptr->id > 0)
763 {
764 /* Identical ID's yield hostility */
765 if (h_ptr->id == q_ptr->id)
766 return TRUE;
767 }
768 #if 0
769 else
770 {
771 /* Check if target belongs to hostile party */
772 if (Players[target]->party == 0 - h_ptr->id)
773 return TRUE;
774 }
775 #endif
776 }
777
778 /* Not hostile */
779 return FALSE;
780 }
781
782
783 /*
784 * The following is a simple hash table, which is used for mapping a player's
785 * ID number to his name. Only players that are still alive are stored in
786 * the table, thus the mapping from a 32-bit integer is very sparse. Also,
787 * duplicate ID numbers are prohibitied.
788 *
789 * The hash function is going to be h(x) = x % n, where n is the length of
790 * the table. For efficiency reasons, n will be a power of 2, thus the
791 * hash function can be a bitwise "and" and get the relevant bits off the end.
792 *
793 * No "probing" is done; if any two ID's map to the same hash slot, they will
794 * be chained in a linked list. This will most likely be a very rare thing,
795 * however.
796 */
797
798 /* The struct to hold a data entry */
799 typedef struct hash_entry hash_entry;
800
801 struct hash_entry
802 {
803 int id; /* The ID */
804 cptr name; /* Player name */
805 struct hash_entry *next; /* Next entry in the chain */
806 };
807
808 /* The hash table itself */
809 static hash_entry *hash_table[NUM_HASH_ENTRIES];
810
811
812 /*
813 * Return the slot in which an ID should be stored.
814 */
hash_slot(int id)815 static int hash_slot(int id)
816 {
817 /* Be very efficient */
818 return (id & (NUM_HASH_ENTRIES - 1));
819 }
820
821 /*
822 * Lookup a player name by ID. Will return NULL if the name doesn't exist.
823 */
lookup_player_name(int id)824 cptr lookup_player_name(int id)
825 {
826 int slot;
827 hash_entry *ptr;
828
829 /* Get the slot */
830 slot = hash_slot(id);
831
832 /* Acquire the pointer to the first element in the chain */
833 ptr = hash_table[slot];
834
835 /* Search the chain, looking for the correct ID */
836 while (ptr)
837 {
838 /* Check this entry */
839 if (ptr->id == id)
840 return ptr->name;
841
842 /* Next entry in chain */
843 ptr = ptr->next;
844 }
845
846 /* Not found */
847 return NULL;
848 }
849
850 /*
851 * Lookup a player's ID by name. Return 0 if not found.
852 */
lookup_player_id(cptr name)853 int lookup_player_id(cptr name)
854 {
855 hash_entry *ptr;
856 int i;
857
858 /* Search in each array slot */
859 for (i = 0; i < NUM_HASH_ENTRIES; i++)
860 {
861 /* Acquire pointer to this chain */
862 ptr = hash_table[i];
863
864 /* Check all entries in this chain */
865 while (ptr)
866 {
867 /* Check this name */
868 if (!strcmp(ptr->name, name))
869 return ptr->id;
870
871 /* Next entry in chain */
872 ptr = ptr->next;
873 }
874 }
875
876 /* Not found */
877 return 0;
878 }
879
880 /*
881 * Add a name to the hash table.
882 */
add_player_name(cptr name,int id)883 void add_player_name(cptr name, int id)
884 {
885 int slot;
886 hash_entry *ptr;
887
888 /* Get the destination slot */
889 slot = hash_slot(id);
890
891 /* Create a new hash entry struct */
892 MAKE(ptr, hash_entry);
893
894 /* Make a copy of the player name in the entry */
895 ptr->name = string_make(name);
896
897 /* Set the entry's id */
898 ptr->id = id;
899
900 /* Add the rest of the chain to this entry */
901 ptr->next = hash_table[slot];
902
903 /* Put this entry in the table */
904 hash_table[slot] = ptr;
905 }
906
907 /*
908 * Delete an entry from the table, by ID.
909 */
delete_player_id(int id)910 void delete_player_id(int id)
911 {
912 int slot;
913 hash_entry *ptr, *old_ptr;
914
915 /* Get the destination slot */
916 slot = hash_slot(id);
917
918 /* Acquire the pointer to the entry chain */
919 ptr = hash_table[slot];
920
921 /* Keep a pointer one step behind this one */
922 old_ptr = NULL;
923
924 /* Attempt to find the ID to delete */
925 while (ptr)
926 {
927 /* Check this one */
928 if (ptr->id == id)
929 {
930 /* Delete this one from the table */
931 if (old_ptr == NULL)
932 hash_table[slot] = ptr->next;
933 else old_ptr->next = ptr->next;
934
935 /* Free the memory in the player name */
936 free((char *)(ptr->name));
937
938 /* Free the memory for this struct */
939 KILL(ptr);
940
941 /* Done */
942 return;
943 }
944
945 /* Remember this entry */
946 old_ptr = ptr;
947
948 /* Advance to next entry in the chain */
949 ptr = ptr->next;
950 }
951
952 /* Not found */
953 return;
954 }
955
956 /*
957 * Delete a player by name.
958 *
959 * This is useful for fault tolerance, as it is possible to have
960 * two entries for one player name, if the server crashes hideously
961 * or the machine has a power outage or something.
962 */
delete_player_name(cptr name)963 void delete_player_name(cptr name)
964 {
965 int id;
966
967 /* Delete every occurence of this name */
968 while ((id = lookup_player_id(name)))
969 {
970 /* Delete this one */
971 delete_player_id(id);
972 }
973 }
974
975 /*
976 * Free player names from memory
977 */
wipe_player_names()978 void wipe_player_names()
979 {
980 int i;
981 hash_entry *ptr;
982 hash_entry *next;
983
984 /* Entry points */
985 for (i = 0; i < NUM_HASH_ENTRIES; i++)
986 {
987 /* Acquire this chain */
988 ptr = hash_table[i];
989
990 /* Check this chain */
991 while (ptr)
992 {
993 next = ptr->next;
994
995 if (ptr->name)
996 string_free(ptr->name);
997 KILL(ptr);
998
999 ptr = next;
1000 }
1001 }
1002 }
1003 /*
1004 * Return a list of the player ID's stored in the table.
1005 */
player_id_list(int ** list)1006 int player_id_list(int **list)
1007 {
1008 int i, len = 0, k = 0;
1009 hash_entry *ptr;
1010
1011 /* Count up the number of valid entries */
1012 for (i = 0; i < NUM_HASH_ENTRIES; i++)
1013 {
1014 /* Acquire this chain */
1015 ptr = hash_table[i];
1016
1017 /* Check this chain */
1018 while (ptr)
1019 {
1020 /* One more entry */
1021 len++;
1022
1023 /* Next entry in chain */
1024 ptr = ptr->next;
1025 }
1026 }
1027
1028 /* Allocate memory for the list */
1029 C_MAKE((*list), len, int);
1030
1031 /* Look again, this time storing ID's */
1032 for (i = 0; i < NUM_HASH_ENTRIES; i++)
1033 {
1034 /* Acquire this chain */
1035 ptr = hash_table[i];
1036
1037 /* Check this chain */
1038 while (ptr)
1039 {
1040 /* Store this ID */
1041 (*list)[k++] = ptr->id;
1042
1043 /* Next entry in chain */
1044 ptr = ptr->next;
1045 }
1046 }
1047
1048 /* Return length */
1049 return len;
1050 }
1051
1052 /* Make player "p_ptr" hostile toward player "q_ptr", if not already */
add_hostility_p(player_type * p_ptr,player_type * q_ptr)1053 void add_hostility_p(player_type *p_ptr, player_type *q_ptr)
1054 {
1055 if (!check_hostile(p_ptr, q_ptr))
1056 {
1057 add_hostility(p_ptr, q_ptr->name);
1058 }
1059 }
1060
1061 /*
1062 * Engage in PVP or Cancel it
1063 *
1064 * This function should be called in each instance of player-to-player damage possibility
1065 * i.e. melee, ranged attacks, magic, splash damage, etc. It checks if pvp is desirable/possible
1066 * and sets some hostility if nessecary.
1067 *
1068 * Modes: 0 -- test 1 -- meele 2 -- direct ranged 3 -- inderect ranged
1069 *
1070 * Returns FALSE if no damage should be dealt
1071 */
pvp_okay(player_type * attacker,player_type * target,int mode)1072 bool pvp_okay(player_type *attacker, player_type *target, int mode)
1073 {
1074 bool intentional = FALSE;
1075 int Depth = attacker->dun_depth;
1076 int party_id = attacker->party;
1077 int hostility = cfg_pvp_hostility;
1078 if (check_hostile(attacker, target)) intentional = TRUE;
1079
1080 /* SAFE DEPTH */
1081 if (cfg_pvp_safedepth > -1 && Depth > -1 && Depth <= cfg_pvp_safedepth) hostility = cfg_pvp_safehostility;
1082 /* SAFE WILDERNESS RADIUS */
1083 if (cfg_pvp_saferadius > -1 && Depth < 0 && wild_info[Depth].radius <= cfg_pvp_saferadius) hostility = cfg_pvp_safehostility;
1084 /* SAFE LEVEL DIFFERENCE */
1085 if (cfg_pvp_safelevel > -1 && abs(attacker->lev - target->lev) > cfg_pvp_safelevel) hostility = cfg_pvp_safehostility;
1086
1087 /* Safe Mode -- Both players must be hostile towards each other (1.1.0) */
1088 if (hostility == 2) {
1089 if (check_hostile(target, attacker) && intentional) return TRUE;
1090 }
1091
1092 /* Normal Mode -- Attacker must be hostile towards his target */
1093 if (hostility == 1) {
1094 /* If this was intentional, make target hostile */
1095 if (intentional)
1096 {
1097 if (mode) add_hostility_p(target, attacker);
1098 return TRUE;
1099 }
1100 }
1101
1102 /* Dangerous Mode -- No hostility needed at all (only for inderect damage) (0.7.2) */
1103 if (hostility == 0) {
1104 if (mode > 1) {
1105 if (!intentional) add_hostility_p(attacker, target);
1106 add_hostility_p(target, attacker);
1107 return TRUE;
1108 } else {
1109 if (mode && intentional) add_hostility_p(target, attacker);
1110 return intentional;
1111 }
1112 }
1113
1114 /* Brutal mode -- all players always fight */
1115 if (hostility == -1) {
1116 /* There's only one way not to fight: be in a party */
1117 if (!(party_id && player_in_party(party_id, target)))
1118 return TRUE;
1119 }
1120
1121 return FALSE;
1122 }
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133