/* Player.m Class definition. Copyright (C) 1995 David Flater. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "cheezmud.h" @implementation Player + new { self = [super new]; ftype = bystander; tty = NULL; return self; } - (void *) getty { return tty; } - setty: (void *) term { tty = term; return self; } - load { char temp[80]; FILE *fp; sprintf (temp, "db/%s", [self mudname]); assert (fp = fopen (temp, "r")); fgets (temp, 80, fp); [self setdef: noeol (temp)]; [self setindef: [self def]]; fgets (temp, 80, fp); [self setlongdesc: noeol (temp)]; fgets (temp, 80, fp); [self teleport: global_find (noeol (temp), 1)]; fscanf (fp, "%f %lu", &stamina, &experience); fclose (fp); return self; } - save { char temp[80]; FILE *fp; sprintf (temp, "db/%s", [self mudname]); assert (fp = fopen (temp, "w")); fprintf (fp, "%s\n", def); fprintf (fp, "%s\n", longdesc); if (location) fprintf (fp, "%s\n", [location mudname]); else fprintf (fp, "start\n"); fprintf (fp, "%f %lu\n", stamina, experience); fclose (fp); return self; } - (int) level { if (experience < 100) return 1; return 1 + (int)(log((double)experience / 100.0 * M_E)); } - (float) priority: (char *) action: (int) numargs { if (numargs == 1) { if (!strcmp (action, "l")) return 10.0; if (!strcmp (action, "names")) return 10.0; if (!strcmp (action, "inv")) return 10.0; if (!strcmp (action, "who")) return 10.0; if (!strcmp (action, "status")) return 10.0; if (!strcmp (action, "smile")) return 10.0; if (!strcmp (action, "frown")) return 10.0; if (!strcmp (action, "giggle")) return 10.0; if (!strcmp (action, "grumble")) return 10.0; if (!strcmp (action, "laugh")) return 10.0; if (!strcmp (action, "yawn")) return 10.0; if (!strcmp (action, "cough")) return 10.0; if (!strcmp (action, "spit")) return 10.0; if (!strcmp (action, "ver")) return 10.0; } if (numargs == 2) { if (!strcmp (action, "examine")) return 10.0; if (!strcmp (action, "get")) return 10.0; if (!strcmp (action, "drop")) return 10.0; if (!strcmp (action, "unbag")) return 10.0; if (!strcmp (action, "read")) return 10.0; if (!strcmp (action, "plunder")) return 10.0; if (!strcmp (action, "hug")) return 10.0; if (!strcmp (action, "finger")) return 10.0; if (!strcmp (action, "kiss")) return 10.0; } return [super priority: action: numargs]; } - echo: (char *) text { text_sock_write (tty, text); text_sock_write (tty, "\n"); if (audit) { id ma; if (!(ma = global_find (mudadmin, 1))) { [self toggle_audit]; return self; } text_sock_write ([ma getty], def); text_sock_write ([ma getty], " echo: "); text_sock_write ([ma getty], text); text_sock_write ([ma getty], "\n"); } return self; } /* We'll get these from objects in our inventory. */ - emote: emoter: (char *) verb_you: (char *) verb_he: (char *) emotion { char temp[160]; sprintf (temp, "%s that you are carrying %s%s.", capitalize ([emoter def]), verb_he, emotion); return [self echo: temp]; } - emote: emoter: (char *) verb_you: (char *) verb_he: dobj: (char *) emotion { char temp[160], a2[80]; if (dobj == self) strcpy (a2, "you"); else strcpy (a2, [dobj def]); sprintf (temp, "%s that you are carrying %s %s%s.", capitalize ([emoter def]), verb_he, a2, emotion); return [self echo: temp]; } - say: emoter: (char *) verb_you: (char *) verb_he: (char *) emotion { char temp[160]; sprintf (temp, "%s that you are carrying %s%s", capitalize ([emoter def]), verb_he, emotion); return [self echo: temp]; } - smile: who { [[who getlocation] emote: who: "smile": "smiles": ""]; return self; } - frown: who { [[who getlocation] emote: who: "look": "looks": " unhappy"]; return self; } - giggle: who { [[who getlocation] emote: who: "giggle": "giggles": ""]; return self; } - grumble: who { [[who getlocation] emote: who: "grumble": "grumbles": ""]; return self; } - laugh: who { [[who getlocation] emote: who: "laugh": "laughs": ""]; return self; } - yawn: who { [[who getlocation] emote: who: "yawn": "yawns": ""]; return self; } - cough: who { [[who getlocation] emote: who: "cough": "coughs": ""]; return self; } - spit: who { [[who getlocation] emote: who: "spit": "spits": ""]; return self; } - ver: who { [who echo: version]; return self; } - hug: who: dobj { [[who getlocation] emote: who: "hug": "hugs": dobj: ""]; return self; } - kiss: who: dobj { [[who getlocation] emote: who: "kiss": "kisses": dobj: ""]; return self; } - finger: who: dobj { [[who getlocation] emote: who: "make a rude gesture at": "makes a rude gesture at": dobj: ""]; return self; } /* This contains code duplicated from Fighter.m. Eventually I may clean */ /* this up, but for now it's easier this way. */ - die { char temp[80]; id c; dead = 1; [location emote: self: "die": "dies": ""]; /* Kluge: theres_a_fight_going_on doesn't work if you get killed in */ /* one swipe, since you are not there for your buddies to query on who */ /* just killed you. This works around that by calling it special just */ /* before you die. */ [location theres_a_fight_going_on]; sprintf (temp, "%s's corpse", indef); c = [[[Corpse new] describe: "corpse": temp: temp: "This is a player who has gotten killed."] setlocation: location]; [contents elementsPerform: @selector(setlocation:) with: c]; /* Penalties for dying */ experience >>= 1; [self setlocation: global_find ("start", 1)]; stamina = 1.0; [self logout]; return self; } - l: who { if (![who getlocation]) { [who echo: "This place is without form, and void. You cannot see or hear or feel\n\ anything, and you are no longer sure if you even exist."]; return self; } [[who getlocation] emote: who: "look": "looks": " around"]; [who echo: capitalize ([[who getlocation] indef])]; [who echo: [[who getlocation] longdesc]]; [[who getlocation] listcontents: who]; return self; } - names: who { id c; int i,n; if ([who getlocation]) { [who echo: "Things in the room:"]; c = [[who getlocation] contents]; for(i=0,n=[c size];i<n;i++) { id whatever = [c at:i]; text_sock_write ([who getty], [whatever mudname]); text_sock_write (tty, "\t"); } text_sock_write ([who getty], "\n"); } c = [who contents]; if ([c isEmpty]) return self; [who echo: "Things you are carrying:"]; for(i=0,n=[c size];i<n;i++) { id whatever = [c at:i]; text_sock_write ([who getty], [whatever mudname]); text_sock_write (tty, "\t"); } text_sock_write ([who getty], "\n"); return self; } - examine: who: dobj { [[who getlocation] emote: who: "examine": "examines": dobj: ""]; [who echo: [dobj longdesc]]; [dobj listcontents: who]; if ([dobj isKindOf: [Fighter class]]) { char temp[80]; float health = [dobj health]; if (health <= 0.33) sprintf (temp, "%s is on the brink of death.", capitalize ([dobj def])); else if (health <= 0.66) sprintf (temp, "%s is hurting real bad.", capitalize ([dobj def])); else if (health < 1.0) sprintf (temp, "%s is kinda beat up.", capitalize ([dobj def])); else sprintf (temp, "%s is uninjured.", capitalize ([dobj def])); [who echo: temp]; } return self; } - read: who: dobj { [dobj getread: who]; return self; } - plunder: who: dobj { if (![dobj isKindOf: [Corpse class]]) { [who echo: "You can only plunder corpses."]; return self; } [[who getlocation] emote: who: "shake down": "shakes down": dobj: ""]; [[dobj contents] elementsPerform: @selector(setlocation:) with: [who getlocation]]; return self; } /* Parse the command line. */ - (int) ohce: (char *) text { if (audit) { id ma; if (!(ma = global_find (mudadmin, 1))) { [self toggle_audit]; } else { text_sock_write ([ma getty], def); text_sock_write ([ma getty], " input: "); text_sock_write ([ma getty], text); text_sock_write ([ma getty], "\n"); } } if (!strcmp (text, "logout")) { [self logout]; return 1; } if (!strcmp (text, "help")) { [self help]; return 1; } if (!strncmp (text, "describe", 8)) { if (strlen (text) < 10) [self setlongdesc: "This player has a null description."]; else [self setlongdesc: text+9]; return 1; } if (!strncmp (text, "say", 3)) { if (strlen (text) < 5) [self echo: "Eh?"]; else [location say: self: "say: ": "says: ": text+4]; return 1; } if (!strncmp (text, "xmit", 4)) { id dobj; if (!(dobj = [self find: "radio": 1])) return 0; if (strlen (text) < 6) [self echo: "Eh?"]; else { [[self getlocation] say: self: "say to the radio: ": "says to the radio: ": text+5]; [dobj xmit: self: text+5]; } return 1; } if (!strncmp (text, "password", 8)) { if (strlen (text) < 10) [self echo: "Password not changed."]; else { set_password (mudname, text+9); [self echo: "Password changed."]; } return 1; } /* Actions */ return [self act: text]; } - who: who { show_users ([who getty]); return self; } - logout { if (!loggedout) { de_notify (tty); /* Quietly drop all possessions */ [contents elementsPerform: @selector(setlocation:) with: location]; [self save]; [super logout]; /* Do this last in case there are more messages */ delmark (tty); } return self; } - help { [self echo: "Commands:"]; [self echo: " logout -- leave the mud"]; [self echo: " l -- (look) look around"]; [self echo: " names -- show names of objects in the room and your inventory"]; [self echo: " who -- show Cheezmud users"]; [self echo: " inv -- show inventory (what you are carrying)"]; [self echo: " n,s,e,w,u,d -- Move north/south/east/west/up/down"]; [self echo: " get name -- pick up something"]; [self echo: " take name -- same as get"]; [self echo: " drop name -- drop something"]; [self echo: " bag name -- put something you are carrying in a sack"]; [self echo: " unbag name -- take it out of a sack"]; [self echo: " read name -- read something"]; [self echo: " kill name -- kill something"]; [self echo: " plunder name -- steal from the dead"]; [self echo: " describe blah blah.... -- change your description"]; [self echo: " password blah blah.... -- change your password"]; [self echo: " say blah blah.... -- speak"]; [self echo: " status -- check your health, etc."]; [self echo: " smile, frown, giggle, grumble, laugh, yawn, cough, spit -- look lively"]; [self echo: " hug name -- hug somebody"]; [self echo: " kiss name -- kiss somebody"]; [self echo: " finger name -- make a rude gesture at somebody"]; [self echo: " ver -- Show cheezmud version"]; [self echo: "To get the second sword, say \"get sword 2\"."]; [self echo: "(That works for any action and for all values of n)"]; [self echo: "Objects that you carry may give you additional commands;"]; [self echo: "examine them to find out how to use them."]; [self echo: "Please remember that long lines will be truncated!"]; [self echo: "Everything is case-sensitive. Most commands are lowercase."]; [self echo: "Type 'names' if you can't figure out how to reference something."]; [self echo: "Armor is not cumulative!"]; return self; } - status: who { char temp[80]; sprintf (temp, "Your current stamina is %f", [who stamina]); [who echo: temp]; sprintf (temp, "Your experience is %lu", [who experience]); [who echo: temp]; return self; } - inv: who { id c; int i,n; c = [who contents]; if ([c isEmpty]) [who echo: "You are not carrying anything."]; else { [who echo: "You are carrying:"]; for(i=0,n=[c size];i<n;i++) { id whatever = [c at:i]; [who echo: capitalize ([whatever indef])]; } } return self; } - get: who: dobj { if ([[who contents] size] >= [who capacity]) { [who echo: "You can't carry any more."]; return self; } /* Can't pick up anything that will fight you. */ if ([dobj isKindOf: [Fighter class]]) { [who echo: "Fat chance."]; return self; } /* Special */ if ([dobj isKindOf: [Bee class]]) { [who echo: "That would be really stupid."]; return self; } [[who getlocation] emote: who: "get ": "gets ": [dobj def]]; [dobj setlocation: who]; return self; } - unbag: who: dobj { if ([[who contents] size] >= [who capacity]) { [who echo: "You can't carry any more."]; return self; } /* In case we somehow stuffed a Tasmanian Devil into a sack.... */ if ([dobj isKindOf: [Fighter class]]) { [who echo: "Fat chance."]; return self; } [[who getlocation] emote: who: "unbag ": "unbags ": [dobj def]]; [dobj setlocation: who]; return self; } - drop: who: dobj { [[who getlocation] emote: who: "drop ": "drops ": [dobj def]]; [dobj setlocation: [who getlocation]]; return self; } - get_experience: (unsigned long) exp { int l; l = [self level]; if (experience < 4000000000) experience += exp; if (experience > 4000000000) experience = 4000000000; if ([self level] - l > 1) [self echo: "Congratulations, you just gained *MULTIPLE* levels!"]; else if ([self level] > l) [self echo: "Congratulations, you just gained a level."]; return self; } - (unsigned long) experience { return experience; } - (float) maxstamina { return [self level] * 15.0; } @end