#include <stdio.h> #include <strings.h> #include <ctype.h> #include "teeny.h" #include "match.h" /* Copyright(C) 1990, Andrew Molitor, All Rights Reserved. This software may be freely used, modified, and redistributed, as long as this copyright message is left intact, and this software is not used to develop any commercial product, or used in any product that is provided on a pay-for-use basis. No warranties whatsoever. This is not guaranteed to compile, nor, in the event that it does compile to binaries, are these binaries guaranteed to perform any function whatsoever. */ /* These routines, together with those in buildcmds.c, wiz.c and speech.c actually implement the commands of TeenyMUD. Hrm. Actually WHO and QUIT are caught in the network interface code. */ long random(); /* Workspace for building strings. None of this sprintf() shit. A little extra space so we can be non-anal about counting */ char cmdwork[BUFFSIZ+16]; do_home(player) int player; { int here,home,list,count,next; char *name,*p; if(get_int_elt(player,HOME,&home) == -1) goto homebomb; if(!exists_object(home)){ notify_player(player,"Your home does not exist!\n"); home = 0; } if(get_int_elt(player,LOC,&here) == -1) goto homebomb; /* Tell people here. */ if(get_str_elt(player,NAME,&name) == -1) goto homebomb; p = cmdwork; if(name != NULL){ for(count = 0;!isspace(*name) && *name && count<BUFFSIZ;count++){ *p++ = *name++; } } strcpy(p," goes home.\n"); notify_oall(player,cmdwork); send_home(player,here); strcpy(p," has arrived.\n"); notify_oall(player,cmdwork); /* Send all the player's stuff home too */ if(get_int_elt(player,CONTENTS,&list) == -1) goto homebomb; while(list != -1){ /* send_home() will change the NEXT element of list */ if(get_int_elt(list,NEXT,&next) == -1) goto homebomb; send_home(list,player); list = next; } /* Tell the player */ notify_player(player,"There's no place like home...\n"); notify_player(player,"There's no place like home...\n"); notify_player(player,"There's no place like home...\n"); do_look(player,(char *) NULL); return; homebomb: notify_bad(player); return; } do_drop(player,arg) int player; char *arg; { int here,obj,flags,i,dest,hereflags; char *p,*q,*name; if(arg == NULL){ notify_player(player,"Drop what?\n"); return; } obj = match_here(player,player,arg,MAT_THINGS | MAT_EXITS); if(obj == -1){ notify_player(player,"You don't have that!\n"); return; } if(get_int_elt(obj,FLAGS,&flags) == -1) goto dropbomb; if(get_int_elt(player,LOC,&here) == -1) goto dropbomb; switch(flags & TYPE_MASK){ case TYP_EXIT: /* Drop from player exits, add to room exits */ list_drop(obj,player,0); /* 0 == exits list */ list_add(obj,here,0); dest = here; /* For setting the LOC later */ break; case TYP_THING: /* Figure out where it's supposed to go */ if(get_int_elt(here,FLAGS,&hereflags) == -1) goto dropbomb; if((flags & STICKY) || (hereflags & TEMPLE)){ /* If the object is STICKY, or this is a temple */ /* Send the object to its home. If you can. */ if(get_int_elt(obj,HOME,&dest) == -1) goto dropbomb; } else if( !(hereflags & STICKY)){ /* If this place is !STICKY, see if there's a dropto */ if(get_int_elt(here,DROPTO,&dest) == -1) goto dropbomb; if(dest == -1){ /* No dropto */ dest = here; } else if(dest == -3){ /* Dropto home */ if(get_int_elt(obj,HOME,&dest) == -1) goto dropbomb; } } else { dest = here; } list_drop(obj,player,1); /* 1 == contents list */ list_add(obj,dest,1); /* Tell the room */ if(get_str_elt(player,NAME,&name) == -1) goto dropbomb; p = cmdwork; if(name != NULL){ for(i = 0; !isspace(*name) && *name && i < BUFFSIZ - 128 ; i++){ *p++ = *name++; } } strcpy(p," dropped "); p += 9; i += 9; if(get_str_elt(obj,NAME,&name) == -1) goto dropbomb; if(name != NULL){ for(q = name;*q && i < BUFFSIZ ; i++){ *p++ = *q++; } } *p++ = '.'; *p++ = '\n'; *p = '\0'; notify_oall(player,cmdwork); if(hereflags & TEMPLE){ int value,wealth,owner; if(get_int_elt(obj,OWNER,&owner) == -1) goto dropbomb; if(owner == player) break; if(get_int_elt(obj,PENNIES,&value) == -1) goto dropbomb; if(get_int_elt(player,PENNIES,&wealth) == -1) goto dropbomb; if(set_int_elt(player,PENNIES,wealth + value) == -1) goto dropbomb; notify_player(player,name); notify_player(player ," is consumed in a burst of flame!\nYou receive "); p = ty_itoa(cmdwork,value); *p = '\0'; notify_player(player,cmdwork); notify_player(player," pennies for your sacrifice.\n"); } break; default: notify_player(player,"You have no business carrying that!\n"); return; } if(set_int_elt(obj,LOC,dest) == -1) goto dropbomb; notify_player(player,"Dropped.\n"); return; dropbomb: notify_bad(player); return; } do_examine(player,arg) int player; char *arg; { int obj,num,len,flags; int *lock; char *p,*msg; if(arg == NULL){ if(get_int_elt(player,LOC,&obj) == -1) goto exbomb; } else { if((obj = resolve_object(player,arg,0)) == -1){ notify_player(player,"I can't find that.\n"); return; } } if(!exists_object(obj)){ notify_player(player,"No such object.\n"); return; } if(!controls(player,obj)){ notify_player(player,"You don't own that!\n"); return; } if(get_int_elt(obj,FLAGS,&flags) == -1) goto exbomb; /* OK. Get this things data, and print it out! */ /* name */ if((len = stuff_name(player,obj,cmdwork,BUFFSIZ)) == -1){ strcpy(cmdwork,"<spammed name>"); } else { cmdwork[len] = '\0'; } notify_player(player,cmdwork);notify_player(player,"\n"); /* Owner */ if(get_int_elt(obj,OWNER,&num) == -1) goto exbomb; if((len = stuff_name(player,num,cmdwork,BUFFSIZ)) == -1){ strcpy(cmdwork,"<spammed name>"); } else { cmdwork[len] = '\0'; } notify_player(player,"Owner: ");notify_player(player,cmdwork); if(get_lock_elt(obj,LOCK,&lock) == -1) goto exbomb; notify_player(player," Lock:"); if(bool_display(player,lock,cmdwork,BUFFSIZ) == -1){ notify_player(player,"Bad lock."); } else { notify_player(player,cmdwork); } if(get_int_elt(obj,PENNIES,&num) == -1) goto exbomb; notify_player(player," Pennies: "); p = ty_itoa(cmdwork,num); *p++ = '\n'; *p = '\0'; notify_player(player,cmdwork); /* desc */ if(get_str_elt(obj,DESC,&p) == -1) goto exbomb; if(p != NULL){ notify_player(player,p);notify_player(player,"\n"); } /* fail, succ, etc.. */ if(get_str_elt(obj,FAIL,&p) == -1) goto exbomb; if(p != NULL){ notify_player(player,"Fail: ");notify_player(player,p); notify_player(player,"\n"); } if(get_str_elt(obj,SUC,&p) == -1) goto exbomb; if(p != NULL){ notify_player(player,"Success: ");notify_player(player,p); notify_player(player,"\n"); } if(get_str_elt(obj,OFAIL,&p) == -1) goto exbomb; if(p != NULL){ notify_player(player,"Ofail: ");notify_player(player,p); notify_player(player,"\n"); } if(get_str_elt(obj,OSUC,&p) == -1) goto exbomb; if(p != NULL){ notify_player(player,"Osuccess: ");notify_player(player,p); notify_player(player,"\n"); } /* home NOTE: Home == DropTo == Dest, depending on object type */ if(get_int_elt(obj,HOME,&num) == -1) goto exbomb; switch(flags & TYPE_MASK){ case TYP_ROOM: notify_player(player,"DropTo: "); msg = "None.\n"; break; case TYP_EXIT: notify_player(player,"Destination: "); msg = "*UNLINKED*\n"; break; case TYP_THING: case TYP_PLAYER: notify_player(player,"Home: "); msg = "Does not exist!\n"; break; } if(exists_object(num)){ if((len = stuff_name(player,num,cmdwork,BUFFSIZ)) == -1){ strcpy(cmdwork,"<spammed name>"); } else { cmdwork[len] = '\0'; } notify_player(player,cmdwork);notify_player(player,"\n"); } else { notify_player(player,msg); } /* location */ if( (flags & TYPE_MASK) != TYP_ROOM){ if(get_int_elt(obj,LOC,&num) == -1) goto exbomb; notify_player(player,"Location: "); if(exists_object(num)){ if((len=stuff_name(player,num,cmdwork,BUFFSIZ)) == -1){ strcpy(cmdwork,"<spammed name>"); } else { cmdwork[len] = '\0'; } notify_player(player,cmdwork); notify_player(player,"\n"); } else { notify_player(player, "Location does not exist! Obj number: "); if(num < 0){ notify_player(player,"-"); num = -num; } p = ty_itoa(cmdwork,num); *p++ = '\n'; *p='\0'; } } /* contents list */ if(get_int_elt(obj,CONTENTS,&num) == -1) goto exbomb; if(num != -1){ notify_player(player,"Contents:\n"); /* last arg == 1 == show dark objects. */ notify_list(player,num,cmdwork,BUFFSIZ,1); } else { notify_player(player,"No contents.\n"); } /* exits list */ if(get_int_elt(obj,EXITS,&num) == -1) goto exbomb; if(num != -1){ notify_player(player,"Exits:\n"); /* last arg == 1 == show dark objects */ notify_list(player,num,cmdwork,BUFFSIZ,1); } else { notify_player(player,"No exits.\n"); } return; exbomb: notify_bad(player); return; } do_take(player,arg) int player; char *arg; { int here,obj,flags,dest; if(arg == NULL){ notify_player(player,"Take what?\n"); return; } if(get_int_elt(player,LOC,&here) == -1) goto takebomb; obj = match_here(player,here,arg,MAT_THINGS | MAT_EXITS); if(obj == -1){ notify_player(player,"I don't see that here.\n"); return; } if(get_int_elt(obj,FLAGS,&flags) == -1) goto takebomb; switch(flags & TYPE_MASK){ case TYP_EXIT: /* If it's unlinked, you can take it */ if(get_int_elt(obj,DESTINATION,&dest) == -1) goto takebomb; if(dest != -1){ notify_player(player,"That exit is linked.\n"); return; } /* Drop it from exits list here. */ list_drop(obj,here,0); /* 0 == exits list */ /* Add it to player exits list. */ list_add(obj,player,0); /* 0 == exits list */ notify_player(player,"Taken\n"); break; case TYP_THING: /* If it's unlocked, you can take it */ if(islocked(player,obj)){ fail_object(player,obj,"You can't pick that up."); return; } /* Do the succ/osucc */ succeed_object(player,obj,"Taken."); /* Drop it from contents list here. */ list_drop(obj,here,1); /* 1 == contents list */ /* Add to player contenst list */ list_add(obj,player,1); /* 1 == contents list */ break; default: notify_player(player,"You can't take that!\n"); return; } if(set_int_elt(obj,LOC,player) == -1) goto takebomb; return; takebomb: notify_bad(player); return; } do_give(player,argone,argtwo) int player; char *argone,*argtwo; { int givee,amount,here; int wealth; int ret; char *name,*p; if(argone == NULL){ notify_player(player,"Give to whom?\n"); return; } if(argtwo == NULL || !isdigit(*argtwo)){ notify_player(player,"What amount would you like to give?\n"); return; } amount = atoi(argtwo); if(get_int_elt(player,LOC,&here) == -1) goto givebomb; if((givee = match_here(player,here,argone,MAT_PLAYERS)) == -1){ notify_player(player,"I don't see that person here.\n"); return; } if((ret = bill_player(player,amount)) == -1) goto givebomb; if(ret == 0) return; /* Give the cash */ if(get_int_elt(givee,PENNIES,&wealth) == -1) goto givebomb; wealth += amount; if(set_int_elt(givee,PENNIES,wealth) == -1) goto givebomb; /* Tell folks. */ if(get_str_elt(player,NAME,&name) == -1) goto givebomb; if(name != NULL){ p = cmdwork; while(!isspace(*name) && *name) *p++ = *name++; *p = '\0'; } notify_player(givee,cmdwork); notify_player(givee," gives you "); p = ty_itoa(cmdwork,amount); *p = '\0'; notify_player(givee,cmdwork); notify_player(givee," pennies.\n"); notify_player(player,"You give "); notify_player(player,cmdwork); notify_player(player," pennies to "); if(get_str_elt(givee,NAME,&name) == -1) goto givebomb; if(name != NULL){ p = cmdwork; while(!isspace(*name) && *name) *p++ = *name++; *p++ = '\n';*p = '\0'; } notify_player(player,cmdwork); return; givebomb: notify_bad(player); return; } do_go(player,arg) int player; char *arg; { struct match *exlist; int here,list,count; if(arg == NULL){ notify_player(player,"Go where?"); return; } if(get_int_elt(player,LOC,&here) == -1) goto gobomb; if(get_int_elt(here,EXITS,&list) == -1) goto gobomb; if((exlist = match_exits(arg,list,&count)) != NULL){ /* Ok. We have a list of exits. Cope with 'em. */ do_go_attempt(player,here,exlist); free_match_list(exlist); return; } else { notify_player(player,"You can't go that way.\n"); } return; gobomb: notify_bad(player); return; } do_help(player) int player; { spit_file(player,"help.txt"); } do_inventory(player) int player; { int list,header; header = 0; if(get_int_elt(player,CONTENTS,&list) == -1) goto invbomb; if(list != -1){ notify_player(player,"You are carrying:\n"); header = 1; notify_list(player,list,cmdwork,BUFFSIZ,1); } if(get_int_elt(player,EXITS,&list) == -1) goto invbomb; if(list != -1){ if(!header){ notify_player(player,"You are carrying:\n"); } notify_list(player,list,cmdwork,BUFFSIZ,1); } do_score(player); return; invbomb: notify_bad(player); return; } do_kill(player,argone,argtwo) int player; char *argone,*argtwo; { int cost,here,victim,flags; int list,next; int ret; char *name,*p,*q,*r; if(argone == NULL){ notify_player(player,"Who would you like to kill?\n"); return; } /* Find who we are supposed to kill */ if(get_int_elt(player,LOC,&here) == -1) goto killbomb; if((victim = match_here(player,here,argone,MAT_PLAYERS)) == -1){ notify_player(player,"I don't see that player here.\n"); return; } /* How much to spend */ if(argtwo != NULL && isdigit(*argtwo)){ cost = atoi(argtwo); if(cost == 0){ notify_player(player,"That's a silly amount!\n"); return; } } else { cost = 10; } if((ret = bill_player(player,cost)) == -1) goto killbomb; if(ret == 0) return; /* Grab the killer-dude's name, and stow it away. We'll want it */ if(get_str_elt(player,NAME,&name) == -1) goto killbomb; p = cmdwork; if(name != NULL){ while(!isspace(*name) && *name){ *p++ = *name++; } } *p = '\0'; /* Have a whack at it. */ if(get_int_elt(victim,FLAGS,&flags) == -1) goto killbomb; if((random() % 100L >= cost) || (flags & WIZARD)){ /* Fail the kill */ notify_player(player,"Your kill attempt failed.\n"); notify_player(victim,cmdwork); notify_player(victim," tried to kill you!\n"); } else { /* The kill succeeded! Do it! */ int wealth; notify_player(victim,cmdwork); notify_player(victim," killed you!\n"); notify_player(victim,"Your insurance policy pays you 50p.\n"); if(get_int_elt(victim,PENNIES,&wealth) == -1) goto killbomb; wealth += 50; if(set_int_elt(victim,PENNIES,wealth) == -1) goto killbomb; /* Tell everyone. p cleverly points at the right spot */ /* No need to count. names are guaranteed pretty short */ strcpy(p," killed ");q = p + 8; if(get_str_elt(victim,NAME,&name) == -1) goto killbomb; r = name; while(!isspace(*r) && *r) *q++ = *r++; strcpy(q,"!\n"); notify_oall(player,cmdwork); p = cmdwork;r = name; while(!isspace(*r) && *r) *p++ = *r++; strcpy(r," has left.\n"); notify_oall(player,cmdwork); /* Send the victim home. */ send_home(victim,here); strcpy(r," has arrived.\n"); notify_oall(victim,cmdwork); /* Send all the player's stuff home too */ if(get_int_elt(victim,CONTENTS,&list) == -1) goto killbomb; while(list != -1){ /* send_home() will change the NEXT element of list */ if(get_int_elt(list,NEXT,&next) == -1) goto killbomb; send_home(list,victim); list = next; } do_look(victim,(char *) NULL); /* Now tell the murderer. */ if(get_str_elt(victim,NAME,&name) == -1) goto killbomb; notify_player(player,"You killed "); if(name != NULL){ p = cmdwork; while(!isspace(*name) && *name){ *p++ = *name++; } *p = '\0'; notify_player(player,cmdwork); } notify_player(player,"!\n"); } return; killbomb: notify_bad(player); return; } do_look(player,arg) int player; char *arg; { int here,contents,len,flags; int obj; char *str; if(arg != NULL){ /* Look at a thing. */ if((obj = match_here(player,player,arg ,MAT_THINGS | MAT_EXITS)) == -1){ if(get_int_elt(player,LOC,&here) == -1) goto lookbomb; if((obj = match_here(player,here,arg,MAT_ANYTHING)) == -1){ notify_player(player,"I don't see that here.\n"); return; } } if(get_str_elt(obj,DESC,&str) == -1) goto lookbomb; if(str == NULL){ str = "You see nothing special."; } notify_player(player,str); notify_player(player,"\n"); if(get_int_elt(obj,CONTENTS,&contents) == -1) goto lookbomb; if(contents != -1){ notify_player(player,"Carrying\n"); /* last argument: 0 == No dark objs.*/ notify_list(player,contents,cmdwork,BUFFSIZ,0); } return; } if(get_int_elt(player,LOC,&here) == -1) goto lookbomb; /* Grab and show the name */ if((len = stuff_name(player,here,cmdwork,BUFFSIZ)) == -1){ strcpy(cmdwork,"<spammed name>"); } else { cmdwork[len] = '\0'; } notify_player(player,cmdwork); notify_player(player,"\n"); /* The desc. */ if(get_str_elt(here,DESC,&str) == -1) goto lookbomb; if(str != NULL){ notify_player(player,str); notify_player(player,"\n"); } /* Do the room succ/osucc thing */ if(islocked(player,here)){ fail_object(player,here,(char *)NULL); } else { succeed_object(player,here,(char *)NULL); } /* Finally spew out the contents list, if the room is unDARK */ if(get_int_elt(here,FLAGS,&flags) == -1) goto lookbomb; if(flags & DARK) return; if(get_int_elt(here,CONTENTS,&contents) == -1) goto lookbomb; /* Is this player the ONLY thing here? */ if(contents == player){ int foo; if(get_int_elt(player,NEXT,&foo) == -1) goto lookbomb; if(foo == -1){ return; } } notify_player(player,"Contents:\n"); /* last arg == 0 == no dark objects */ notify_list(player,contents,cmdwork,BUFFSIZ,0); return; lookbomb: notify_bad(player); return; } do_news(player) int player; { spit_file(player,"news.txt"); } do_rob(player,arg) int player; char *arg; { int robee,wealth,here; char *name,*p; if(get_int_elt(player,LOC,&here) == -1) goto robbomb; if((robee = match_here(player,here,arg,MAT_PLAYERS)) == -1){ notify_player(player,"I don't see that player here.\n"); return; } if(islocked(player,robee)){ fail_object(player,robee,"Your conscience tells you not to."); return; } /* Do the rob. */ if(get_int_elt(robee,PENNIES,&wealth) == -1); if(wealth <= 0){ if(get_str_elt(robee,NAME,&name) == -1) goto robbomb; p = cmdwork; if(name != NULL){ while(!isspace(*name) && *name) *p++ = *name++; } strcpy(p," is penniless."); succeed_object(player,robee,cmdwork); return; } if(set_int_elt(robee,PENNIES,wealth-1) == -1) goto robbomb; if(get_int_elt(player,PENNIES,&wealth) == -1) goto robbomb; if(set_int_elt(player,PENNIES,wealth+1) == -1) goto robbomb; succeed_object(player,robee,"You stole a penny."); if(get_str_elt(player,NAME,&name) == -1) goto robbomb; p = cmdwork; if(name != NULL){ while(!isspace(*name) && *name) *p++ = *name++; } strcpy(p," stole a penny.\n"); notify_player(robee,cmdwork); return; robbomb: notify_bad(player); return; } do_score(player) int player; { int wealth; char *p; if(get_int_elt(player,PENNIES,&wealth) == -1) goto scorebomb; notify_player(player,"You have "); p = ty_itoa(cmdwork,wealth); *p = '\0'; notify_player(player,cmdwork); notify_player(player," pennies, for what it's worth.\n"); return; scorebomb: notify_bad(player); return; } do_password(player,argone,argtwo) int player; char *argone,*argtwo; { char *pwd,*p; if(argtwo == NULL){ notify_player(player,"usage: @password oldpwd=newpwd\n"); return; } if(get_str_elt(player,NAME,&pwd) == -1) goto passbomb; if(pwd == NULL){ notify_player(player,"You have no name OR password!\n"); return; } /* Copy the actual name into cmdwork */ p = cmdwork; while(!isspace(*pwd) && *pwd) *p++ = *pwd++; /* Find the current pwd */ while(isspace(*pwd) && *pwd) pwd++; if(strcmp(pwd,argone) != 0){ notify_player(player,"Incorrect password.\n"); return; } /* OK. Set the password up in cmdwork */ *p++ = ' '; while(*argtwo) *p++ = *argtwo++; *p++ = '\0'; if(set_str_elt(player,NAME,cmdwork) == -1) goto passbomb; notify_player(player,"Password changed.\n"); return; passbomb: notify_bad(player); return; } do_stats(player) int player; { char *p; extern int actual_objects; notify_player(player,"The universe contains "); p = ty_itoa(cmdwork,actual_objects); *p = '\0'; notify_player(player,cmdwork); notify_player(player," objects.\n"); } do_set(player,argone,argtwo) int player; char *argone,*argtwo; { int obj,unset,newflag,objflags,playerflags; char *msg; if(argtwo == NULL){ notify_player(player,"Set what?\n"); return; } obj = resolve_object(player,argone,0); /* No *<playername> */ if(!exists_object(obj) || !controls(player,obj)){ notify_player(player,"You can't set that!\n"); return; } /* Okie. What's this doof want to set? */ if(*argtwo == '!'){ unset = 1; argtwo++; } else { unset = 0; } if(stringprefix(argtwo,"LINK_OK")) newflag = LINK_OK; else if(stringprefix(argtwo,"STICKY")) newflag = STICKY; else if(stringprefix(argtwo,"DARK")) newflag = DARK; else if(stringprefix(argtwo,"WIZARD")) newflag = WIZARD; else if(stringprefix(argtwo,"TEMPLE")) newflag = TEMPLE; else { notify_player(player,"I don't understand that flag.\n"); return; } /* Check legalities */ if(get_int_elt(player,FLAGS,&playerflags) == -1) goto setbomb; if(get_int_elt(obj,FLAGS,&objflags) == -1) goto setbomb; if(!(playerflags & WIZARD)){ /* Wizards can do anything. */ if(newflag == DARK && (objflags & TYPE_MASK) != TYP_ROOM){ notify_player(player,"Permission denied.\n"); return; } else if(newflag == TEMPLE || newflag == WIZARD){ notify_player(player,"Permission denied.\n"); return; } } /* Set the flags */ if(unset){ objflags &= ~newflag; msg = "Flag unset.\n"; } else { objflags |= newflag; msg = "Flag set.\n"; } if(set_int_elt(obj,FLAGS,objflags) == -1) goto setbomb; notify_player(player,msg); return; setbomb: notify_bad(player); return; }