|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 21117 (0x527d)
Types: TextFile
Names: »comptbl.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Cubes/comptbl.c«
/* vi:set sw=4 ts=4: */
#ifndef lint
static char sccsid[] = "@(#)comptbl.c 5.1 (G.M. Paris) 89/01/22";
#endif lint
/*
**
** cubes 5.1 Copyright 1989 Gregory M. Paris
** Permission granted to redistribute on a no charge basis.
** All other rights are reserved.
**
*/
/*
** This module is a real mixed bag. Various functions and definitions
** that were necessary to compile a standalone history file analyzer
** have been moved here from all over, but mainly from cubeserver.c.
** It still takes some dummy stubs to compile...
*/
#include <stdio.h>
#include <syslog.h>
#include <strings.h>
#include "cubes.h"
extern int winscore;
extern boolean inprogress;
extern winpref gametype;
extern boolean nameinuse();
extern boolean iskamelion();
extern boolean kamelionplaying();
extern unsigned nhist;
extern history *hist;
extern history *histbyname();
extern char *malloc();
extern char *moniker();
player plr[PLAYERS]; /* defined here for standalone use */
extern strategy st_basic, st_merrier, st_respect, st_twohater, st_greedy;
extern strategy st_picky, st_finicky, st_choosy, st_kamelion, st_fickle;
extern temper te_robot, te_antsy, te_tracker, te_chicken, te_gambler;
extern temper te_crafty, te_shakey, te_zeno, te_goalie, te_best;
extern temper te_kamelion, te_schizo;
/*
** comptbl: list of available computer players
** comments indicate the source of each name
*/
computer comptbl[] = {
{ "CUBEX", &st_basic, &te_robot, Nopref }, /* original */
{ "UNIBLAB", &st_merrier, &te_antsy, Fickle }, /* Jetsons */
{ "Rosie", &st_choosy, &te_goalie, Nopref }, /* Jetsons */
{ "Brainiac", &st_twohater, &te_chicken, Standard }, /* comics */
{ "Wotan", &st_greedy, &te_goalie, Nopref }, /* Dr. Who */
{ "K-2", &st_choosy, &te_robot, Nopref }, /* Dr. Who */
{ "K-9", &st_basic, &te_goalie, Nopref }, /* Dr. Who */
{ "M5", &st_merrier, &te_tracker, Nopref }, /* Star Trek */
{ "NOMAD", &st_respect, &te_goalie, Nopref }, /* Star Trek */
{ "Landrew", &st_twohater, &te_gambler, Blitz }, /* Star Trek */
{ "Norman", &st_choosy, &te_zeno, Nopref }, /* Star Trek */
{ "Stella 500", &st_picky, &te_antsy, Nopref }, /* Star Trek */
{ "Alice 3", &st_choosy, &te_tracker, Nopref }, /* Star Trek */
{ "The Old Man", &st_merrier, &te_chicken, Fstand }, /* T. Zone */
{ "Agnes", &st_respect, &te_gambler, Blitz }, /* T. Zone */
{ "Dr. Theopolis", &st_twohater, &te_robot, Nopref }, /* B. Rogers */
{ "Tweekie", &st_greedy, &te_antsy, Nopref }, /* B. Rogers */
{ "Gort", &st_picky, &te_tracker, Nopref }, /* tDtESS */
{ "Robbie", &st_basic, &te_chicken, Standard }, /* various */
{ "HAL9000", &st_merrier, &te_gambler, Fblitz }, /* Clarke */
{ "SAL9000", &st_respect, &te_robot, Nopref }, /* Clarke */
{ "Mother", &st_twohater, &te_antsy, Nopref }, /* Alien */
{ "Ashe", &st_greedy, &te_tracker, Nopref }, /* Alien */
{ "Bishop", &st_picky, &te_chicken, Standard }, /* Aliens */
{ "W.O.P.R.", &st_basic, &te_gambler, Blitz }, /* War Games */
{ "The Terminator", &st_merrier, &te_robot, Nopref }, /* title role */
{ "Number Five", &st_respect, &te_antsy, Nopref }, /* title role */
{ "Jenkins", &st_twohater, &te_tracker, Nopref }, /* Simak */
{ "R. Daneel Olivaw",&st_greedy, &te_chicken, Standard }, /* Asimov */
{ "GAX", &st_picky, &te_gambler, Blitz }, /* Software */
{ "TEX", &st_basic, &te_robot, Nopref }, /* Software */
{ "MEX", &st_choosy, &te_antsy, Nopref }, /* Software */
{ "BEX", &st_respect, &te_tracker, Nopref }, /* Software */
{ "DEX", &st_choosy, &te_chicken, Standard }, /* Software */
{ "LIBEX", &st_greedy, &te_gambler, Blitz }, /* Wetware */
{ "Mr. Frostee", &st_picky, &te_robot, Nopref }, /* Software */
{ "Ralph Numbers", &st_basic, &te_antsy, Nopref }, /* Software */
{ "Wagstaff", &st_merrier, &te_goalie, Nopref }, /* Software */
{ "Berenice", &st_respect, &te_chicken, Standard }, /* Wetware */
{ "Emul", &st_twohater, &te_goalie, Nopref }, /* Wetware */
{ "Ulalume", &st_greedy, &te_robot, Nopref }, /* Wetware */
{ "Oozer", &st_picky, &te_goalie, Nopref }, /* Wetware */
{ "Kkandio", &st_basic, &te_tracker, Nopref }, /* Wetware */
{ "Jander Panell", &st_finicky, &te_crafty, Fickle }, /* Asimov */
{ "Eddie", &st_picky, &te_shakey, Fickle }, /* HHGttG */
{ "Artoo Detoo", &st_basic, &te_zeno, Nopref }, /* Star Wars */
{ "Marvin", &st_finicky, &te_tracker, Nopref }, /* HHGttG */
{ "Giskard Reventlov",&st_picky, &te_crafty, Fickle }, /* Asimov */
{ "Speedy", &st_basic, &te_shakey, Fblitz }, /* Asimov */
{ "See Threepio", &st_finicky, &te_zeno, Nopref }, /* Star Wars */
{ "R. Geronimo", &st_basic, &te_crafty, Fickle }, /* Asimov */
{ "Pondermatic", &st_finicky, &te_shakey, Fstand }, /* HHGttG */
{ "Deep Thought", &st_picky, &te_zeno, Nopref }, /* HHGttG */
{ "Xoanon", &st_finicky, &te_antsy, Fickle }, /* Dr. Who */
{ "R. Sammy", &st_merrier, &te_crafty, Fickle }, /* Asimov */
{ "Helen", &st_merrier, &te_zeno, Nopref }, /* Wetware */
{ "Huey", &st_merrier, &te_shakey, Blitz }, /* Sil. Run. */
{ "Duey", &st_respect, &te_shakey, Blitz }, /* Sil. Run. */
{ "Luey", &st_choosy, &te_shakey, Blitz }, /* Sil. Run. */
{ "the robot (B9)", &st_finicky, &te_robot, Nopref }, /* L.i.Space */
{ "SV7", &st_respect, &te_zeno, Nopref }, /* Dr. Who */
{ "Earth", &st_choosy, &te_gambler, Fstand }, /* HHGttG */
{ "Roderick", &st_respect, &te_crafty, Fickle }, /* Sladek */
{ "Tik-Tok", &st_choosy, &te_crafty, Fickle }, /* Sladek */
{ "IG-88", &st_finicky, &te_goalie, Nopref }, /* S. Wars II */
{ "Roger Korby", &st_twohater, &te_zeno, Fickle }, /* Star Trek */
{ "Rayna Kapec", &st_finicky, &te_chicken, Nopref }, /* Star Trek */
{ "V'ger", &st_finicky, &te_gambler, Nopref }, /* ST:TMP */
{ "M. Gargantubrain",&st_greedy, &te_crafty, Standard }, /* HHGttG */
{ "Neutron Wrangler",&st_greedy, &te_shakey, Standard }, /* HHGttG */
{ "M.P. Titan Muller",&st_greedy, &te_zeno, Standard }, /* HHGttG */
{ "Ruk", &st_twohater, &te_crafty, Fickle }, /* Star Trek */
{ "Andrea", &st_twohater, &te_shakey, Fickle }, /* Star Trek */
{ "Orac", &st_choosy, &te_best, Nopref }, /* Blake's 7 */
/*
** If you have more names, mail them to me...
**
** Kamelion must be last.
*/
{ "Kamelion", &st_kamelion, &te_kamelion, Fickle } /* Dr. Who */
};
#define COMPUTERS (sizeof comptbl / sizeof comptbl[0])
int computers = COMPUTERS;
computer *pkamelion = &comptbl[COMPUTERS - 1];
computer proxy = { "**proxy**", &st_fickle, &te_schizo, Nopref };
/*
** initcomptbl: initialize computer table (no-op)
*/
initcomptbl() { }
/*
** compbyname: return a pointer to the computer with the matching name
*/
computer *
compbyname(name)
register char *name;
{
register int n;
for(n = 0;n < computers;++n)
if(strncmp(name, comptbl[n].c_name, IDLEN) == 0)
return &comptbl[n];
return (computer *)0;
}
/*
** addcomp: add the COMP computer
** a game is never in progress when this happens
*/
addcomp(c)
int c;
{
plr[c].p_fd = -1;
plr[c].p_score = 0;
plr[c].p_onboard = False;
plr[c].p_stat = Computer;
plr[c].p_id[0] = '\0'; /* non-proxies are null */
plr[c].p_computer = &comptbl[0];
strcpy(plr[c].p_name, plr[c].p_computer->c_name);
setpref(c);
}
/*
** pickproxy: give this player the proxy personality
** Doesn't change p_stat, in case this is a temporary proxy.
*/
pickproxy(c)
int c;
{
if(plr[c].p_computer != &proxy)
plr[c].p_computer = &proxy;
if(plr[c].p_mood == NOMOOD)
plr[c].p_mood = randint(MAXMOOD);
/* don't change preference */
}
/*
** nextupcmp: comparison function for producing next-up order
** sorts computers before humans
** sorts the COMP computer before other computers
** sorts computers to have best play more often than worst
** NOTE: histsort() must be called first for proper operation.
*/
nextupcmp(h1, h2)
history *h1, *h2;
{
register int diff;
/*
** Computers before humans.
*/
if((h1->h_computer == 0) != (h2->h_computer == 0))
return h1->h_computer == 0 ? 1 : -1;
/*
** COMP computer before all others.
*/
if(h1->h_computer == &comptbl[0])
return -1;
if(h2->h_computer == &comptbl[0])
return 1;
/*
** We cycle through the list of computers, but with the modification
** that the higher ranked players will play more often than the lower.
*/
diff = 2 * (h1->h_lastgame - h2->h_lastgame);
diff += h1->h_rank - h2->h_rank;
if(diff != 0)
return diff;
/*
** For tie breaking, the player with the least games played goes next.
*/
if((diff = h1->h_games - h2->h_games) != 0)
return diff;
/*
** For further tiebreaking, prefer more wins, higher points, and
** higher turn average, in that order. (Note: games equal here.)
*/
if((diff = h2->h_wins - h1->h_wins) != 0)
return diff;
if((diff = h2->h_points - h1->h_points) != 0)
return diff;
if((diff = h2->h_avgturn - h1->h_avgturn) != 0)
return diff;
return 0;
}
/*
** pickcomputer: give this player an inactive computer personality
*/
pickcomputer(c)
int c;
{
register int comp;
register history *thist;
unsigned size;
static boolean allinhist = False;
plr[c].p_stat = Computer;
plr[c].p_id[0] = '\0'; /* not a proxy */
plr[c].p_mood = randint(MAXMOOD); /* mood set on entering */
/*
** Usually, we'd like to select computers that haven't played much
** (the more highly ranked the better), but this method will never
** pick a computer that's not in the history file. What we do then
** is randomly select this method, and if it fails, we still fall
** back on random selection from the comptbl.
*/
thist = 0;
if(randint(100) <= 85) {
size = nhist * sizeof *hist;
if((thist = (history *)malloc(size)) == 0)
syslog(LOG_WARNING, "pickcomputer: no memory for dup history");
}
if(thist != 0) {
/*
** Copy the history info and sort it into a desirable order.
** Step through the list to find a computer player.
*/
bcopy((char *)hist, (char *)thist, (int)size);
qsort((char *)thist, (int)nhist, sizeof *thist, nextupcmp);
for(comp = 0;comp < (int)nhist;++comp) {
if((thist+comp)->h_computer == 0)
continue;
if(randint(3) != 1) /* 67% chance */
continue;
plr[c].p_computer = (thist+comp)->h_computer;
if(iskamelion(c) == True) {
if(kamelionplaying(c) == True)
continue;
setkamelion(c);
} else {
if(nameinuse(c, plr[c].p_computer->c_name) == True)
continue;
strcpy(plr[c].p_name, plr[c].p_computer->c_name);
setpref(c);
if(inprogress == True) { /* picky late joiners */
switch(plr[c].p_pref) {
case Fstand: if(gametype != Standard) continue; break;
case Fblitz: if(gametype != Blitz) continue; break;
case Standard: if(gametype != Standard) continue; break;
case Blitz: if(gametype != Blitz) continue; break;
}
}
}
free((char *)thist);
return;
}
free((char *)thist);
}
/*
** Check to see if there are any computer players that have never played.
** If one is found use it. If none are found, make sure we don't waste
** our time here again. We don't do this every time we get here because
** we want to ration out the new computers.
*/
if(allinhist == False && randint(100) <= 20) {
for(comp = 1;comp < computers;++comp) {
if(comptbl[comp].c_name[0] == '\0') /* placeholder */
continue;
if(histbyname(comptbl[comp].c_name) != 0)
continue;
plr[c].p_computer = &comptbl[comp];
if(iskamelion(c) == True) {
if(kamelionplaying(c) == True)
continue;
setkamelion(c);
} else {
if(nameinuse(c, plr[c].p_computer->c_name) == True)
continue;
strcpy(plr[c].p_name, plr[c].p_computer->c_name);
setpref(c);
if(inprogress == True) { /* semi-picky late joiners */
switch(plr[c].p_pref) {
case Fstand: if(gametype != Standard) continue; break;
case Fblitz: if(gametype != Blitz) continue; break;
}
}
}
return;
}
allinhist = True;
}
/*
** Randomly select a computer from the comptbl. This routine cannot
** fail as long as PLAYERS is less than the number of computers.
*/
for(;;) {
comp = randint(computers - 1); /* don't pick zero */
if(comptbl[comp].c_name[0] == '\0') /* placeholder */
continue;
plr[c].p_computer = &comptbl[comp];
if(iskamelion(c) == True) {
if(kamelionplaying(c) == True)
continue;
setkamelion(c);
} else {
if(nameinuse(c, plr[c].p_computer->c_name) == True)
continue;
strcpy(plr[c].p_name, plr[c].p_computer->c_name);
setpref(c);
if(inprogress == True) { /* semi-picky late joiners */
switch(plr[c].p_pref) {
case Fstand: if(gametype != Standard) continue; break;
case Fblitz: if(gametype != Blitz) continue; break;
}
}
}
return;
}
}
/*
** setkamelion: Kamelion adopts the personality of other computers
** and the moniker of other players
*/
setkamelion(c)
{
register int comp;
register char *aka;
register history *phist;
/*
** Pick a computer player's personality for Kamelion to mimic.
** Kamelion wants to be a good player, so we pick from the top
** of the history (best ranked players).
*/
for(comp = 0;comp < nhist;++comp) {
phist = hist + comp;
if(phist->h_computer == 0 || phist->h_computer == pkamelion)
continue;
if(inprogress == True) { /* semi-picky late joiners */
switch(phist->h_computer->c_pref) {
case Fstand: if(gametype != Standard) continue; break;
case Fblitz: if(gametype != Blitz) continue; break;
}
}
if(randint(4) != 1) /* 75% chance */
continue;
pkamelion->c_strategy->s_func = phist->h_computer->c_strategy->s_func;
pkamelion->c_temper->t_func = phist->h_computer->c_temper->t_func;
pkamelion->c_pref = phist->h_computer->c_pref;
break;
}
/*
** If the above method failed, just select randomly from comptbl.
*/
if(comp >= nhist) {
do {
comp = randint(computers - 1); /* don't pick zero, COMP */
} while(&comptbl[comp] == pkamelion);
pkamelion->c_strategy->s_func = comptbl[comp].c_strategy->s_func;
pkamelion->c_temper->t_func = comptbl[comp].c_temper->t_func;
pkamelion->c_pref = comptbl[comp].c_pref;
}
/*
** Pick a name for Kamelion to assume. Kamelion appears to be a proxy.
*/
while(nameinuse(c, (aka = moniker())) == True)
;
strncpy(plr[c].p_name, aka, NAMELEN);
plr[c].p_name[NAMELEN-1] = '\0';
strncpy(plr[c].p_id, pkamelion->c_name, IDLEN);
plr[c].p_id[IDLEN-1] = '\0';
/*
** Make sure that p_computer is set. Set preference.
*/
plr[c].p_computer = pkamelion;
setpref(c);
}
/*
** setpref: set p_pref for a computer player
*/
setpref(c)
{
player *p = &plr[c];
if(p->p_computer != 0) {
if((p->p_pref = p->p_computer->c_pref) == Fickle) {
switch(randint(9)) {
case 1: case 5: p->p_pref = Standard; break;
case 2: case 6: p->p_pref = Blitz; break;
case 3: p->p_pref = Fstand; break;
case 4: p->p_pref = Fblitz; break;
default: p->p_pref = Nopref; break;
}
}
}
}
/*
** iscomp: return True if player is the COMP computer
*/
boolean
iscomp(c)
{
if(plr[c].p_stat != Computer)
return False;
if(plr[c].p_computer != &comptbl[0])
return False;
return True;
}
/*
** isproxy: return True if player is a proxy computer
** There are two kinds of proxies, permanent and temporary.
** Permanent proxy: p_stat == Computer, p_computer == &proxy.
** Temporary proxy: p_stat == Active, p_computer == &proxy.
*/
boolean
isproxy(c)
{
if(plr[c].p_computer == &proxy)
if(plr[c].p_stat == Computer || plr[c].p_stat == Active)
return True;
return False;
}
/*
** iskamelion: return True if player is Kamelion
*/
boolean
iskamelion(c)
{
if(plr[c].p_stat != Computer)
return False;
if(plr[c].p_computer != pkamelion)
return False;
return True;
}
/*
** nameinuse: return True if name in use by other than numbered player
*/
boolean
nameinuse(c, name)
int c;
char *name;
{
register int cc;
for(cc = 0;cc < PLAYERS;++cc)
if(cc != c && plr[cc].p_stat != Inactive)
if(strncmp(plr[cc].p_name, name, NAMELEN-1) == 0)
return True;
return False;
}
/*
** kamelionplaying: return True if Kamelion is already playing
*/
boolean
kamelionplaying(comp)
{
register int c;
for(c = 0;c < PLAYERS;++c)
if(c != comp && iskamelion(c) == True)
return True;
return False;
}
/*
** highscore: find highest score amongst other players
** If phighc is not zero, stores index of high scorer
** or -1 if there's a tie.
*/
highscore(comp, phighc)
int comp, *phighc;
{
register int c;
int high, highc;
high = 0, highc = -1;
for(high = c = 0;c < PLAYERS;++c) if(c != comp) {
switch(plr[c].p_stat) {
case Computer:
case Active:
if(plr[c].p_score > high)
high = plr[(highc = c)].p_score;
else if(plr[c].p_score == high)
highc = -1;
break;
}
}
if(phighc != 0)
*phighc = highc;
return high;
}
/*
** sc_: structure for sorting scores
*/
struct sc_ { int sc_c, sc_p; };
/*
** sc_comp: compare struct sc_ values, largest sc_p first
*/
static int
sc_comp(s1, s2)
struct sc_ *s1, *s2;
{
return s2->sc_p - s1->sc_p;
}
/*
** closescore: find the highest score that's close enough to compete with
** If closec is not zero, stores index of the selected scorer
** or -1 if there's a tie.
*/
closescore(comp, pclosec)
int comp, *pclosec;
{
register int c;
int mine, diff;
int high, highc;
struct sc_ sc[PLAYERS];
#define UPPERLIM 3000 /* beyond this is too far ahead */
#define LOWERLIM -1000 /* below this is too far behind */
/*
** Sort the scores best first.
*/
for(c = 0;c < PLAYERS;++c) {
if((sc[c].sc_c = c) == comp) {
sc[c].sc_p = -1; /* cause end search */
continue;
}
switch(plr[c].p_stat) {
case Computer:
case Active:
sc[c].sc_p = plr[c].p_score;
break;
default:
sc[c].sc_p = -2; /* cause end search */
break;
}
}
qsort((char *)sc, PLAYERS, sizeof sc[0], sc_comp);
/*
** Find a close score to track.
*/
mine = plr[comp].p_score;
high = 0, highc = -1;
for(c = 0;c < PLAYERS && sc[c].sc_p >= 0;++c) {
if((diff = sc[c].sc_p - mine) > UPPERLIM)
continue;
if(diff < LOWERLIM && c > 0)
--c;
high = sc[c].sc_p;
if(pclosec != 0) {
if(c+1 >= PLAYERS || sc[c+1].sc_p != high)
highc = sc[c].sc_c;
}
break;
}
if(pclosec != 0)
*pclosec = highc;
return high;
#undef UPPERLIM
#undef LOWERLIM
}
/*
** lowscore: report the lowest score
** Also calculates an average squander value.
*/
lowscore(psqu)
int *psqu;
{
register int cc, low, squ, n;
#define HIGHVAL (2^15) /* "impossible" high score */
/*
** Look for lowest score. Sum squandered points.
*/
low = HIGHVAL, squ = 0, n = 0;
for(cc = 0;cc < PLAYERS;++cc) {
switch(plr[cc].p_stat) {
case Active:
case Computer:
if(plr[cc].p_score < low)
low = plr[cc].p_score;
if(psqu != 0)
squ += plr[cc].p_squander, ++n;
break;
}
}
if(low == HIGHVAL)
low = 0;
/*
** If a non-null pointer was passed, calculate an
** average squandered value and pass it back.
*/
if(psqu != 0) {
if(n == 0)
*psqu = 0; /* no players?! */
else {
squ = (squ + n - 1) / n; /* average, rounded up */
squ = squ - (squ % P_FIVE); /* mult. of P_FIVE, rounded down */
*psqu = squ;
}
}
return low;
#undef HIGHVAL
}
/*
** winner: return winner number or -1 if none
*/
winner()
{
register int c;
register int high, next;
register int highc;
/*
** Find high score. If less than winscore, no winner.
*/
for(high = c = 0;c < PLAYERS;++c) {
switch(plr[c].p_stat) {
case Computer:
case Active:
if(plr[c].p_score > high)
high = plr[(highc = c)].p_score;
break;
}
}
if(high < winscore)
return -1;
/*
** Find next to highest score. If margin is less than
** WINMARGIN, there's no winner yet.
*/
for(next = c = 0;c < PLAYERS;++c) {
if(c == highc)
continue;
switch(plr[c].p_stat) {
case Computer:
case Active:
if(plr[c].p_score > next)
next = plr[c].p_score;
break;
}
}
if(high - next < WINMARGIN)
return -1;
/*
** We have a winner!
*/
return highc;
}
/*
** plrcmp: player comparison function
*/
plrcmp(p1, p2)
player *p1, *p2;
{
int diff;
/*
** Sort by status first.
*/
if(p1->p_stat == p2->p_stat) {
switch(p1->p_stat) {
case Inactive:
case Watching:
case Waiting:
return 0;
}
} else {
switch(p2->p_stat) {
case Computer: diff = 3; break; /* Computer == Active */
case Active: diff = 3; break; /* Computer == Active */
case Waiting: diff = 2; break;
case Watching: diff = 1; break;
default: diff = 0; break;
}
switch(p1->p_stat) {
case Computer: diff -= 3; break; /* Computer == Active */
case Active: diff -= 3; break; /* Computer == Active */
case Waiting: diff -= 2; break;
case Watching: diff -= 1; break;
default: break;
}
if(diff != 0) return diff;
}
/*
** Sort in order of increasing score.
*/
if((diff = p1->p_score - p2->p_score) != 0)
return diff;
/*
** Put Computer players after humans.
*/
if(p1->p_stat != p2->p_stat)
return (p1->p_stat == Computer) ? 1 : -1;
/*
** Sort alphabetically.
*/
return strcmp(p1->p_name, p2->p_name);
}