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