struct obj_data *unequip_char(struct char_data *ch, int pos) { int j; struct obj_data *obj; if ((pos < 0 || pos >= NUM_WEARS) || GET_EQ(ch, pos) == NULL) { core_dump(); return (NULL); } obj = GET_EQ(ch, pos); obj->worn_by = NULL; obj->worn_on = -1; if (GET_OBJ_TYPE(obj) == ITEM_ARMOR) GET_AC(ch) += apply_ac(ch, pos); if (IN_ROOM(ch) != NOWHERE) { if (pos == WEAR_LIGHT && GET_OBJ_TYPE(obj) == ITEM_LIGHT) if (GET_OBJ_VAL(obj, 2)) /* if light is ON */ world[IN_ROOM(ch)].light--; } else log("SYSERR: IN_ROOM(ch) = NOWHERE when unequipping char %s.", GET_NAME(ch)); GET_EQ(ch, pos) = NULL; for (j = 0; j < MAX_OBJ_AFFECT; j++) affect_modify_ar(ch, obj->affected[j].location, obj->affected[j].modifier, GET_OBJ_AFFECT(obj), FALSE); affect_total(ch); return (obj); }
/* Return the effect of a piece of armor in position eq_pos */ static int apply_ac(struct char_data *ch, int eq_pos) { int factor; if (GET_EQ(ch, eq_pos) == NULL) { core_dump(); return (0); } if (!(GET_OBJ_TYPE(GET_EQ(ch, eq_pos)) == ITEM_ARMOR)) return (0); switch (eq_pos) { case WEAR_BODY: factor = 3; break; /* 30% */ case WEAR_HEAD: factor = 2; break; /* 20% */ case WEAR_LEGS: factor = 2; break; /* 20% */ default: factor = 1; break; /* all others 10% */ } return (factor * GET_OBJ_VAL(GET_EQ(ch, eq_pos), 0)); }
void equip_char(struct char_data *ch, struct obj_data *obj, int pos) { int j; if (pos < 0 || pos >= NUM_WEARS) { core_dump(); return; } if (GET_EQ(ch, pos)) { log("SYSERR: Char is already equipped: %s, %s", GET_NAME(ch), obj->short_description); return; } if (obj->carried_by) { log("SYSERR: EQUIP: Obj is carried_by when equip."); return; } if (IN_ROOM(obj) != NOWHERE) { log("SYSERR: EQUIP: Obj is in_room when equip."); return; } if (invalid_align(ch, obj) || invalid_class(ch, obj)) { act("You are zapped by $p and instantly let go of it.", FALSE, ch, obj, 0, TO_CHAR); act("$n is zapped by $p and instantly lets go of it.", FALSE, ch, obj, 0, TO_ROOM); /* Changed to drop in inventory instead of the ground. */ obj_to_char(obj, ch); return; } GET_EQ(ch, pos) = obj; obj->worn_by = ch; obj->worn_on = pos; if (GET_OBJ_TYPE(obj) == ITEM_ARMOR) GET_AC(ch) -= apply_ac(ch, pos); if (IN_ROOM(ch) != NOWHERE) { if (pos == WEAR_LIGHT && GET_OBJ_TYPE(obj) == ITEM_LIGHT) if (GET_OBJ_VAL(obj, 2)) /* if light is ON */ world[IN_ROOM(ch)].light++; } else log("SYSERR: IN_ROOM(ch) = NOWHERE when equipping char %s.", GET_NAME(ch)); for (j = 0; j < MAX_OBJ_AFFECT; j++) affect_modify_ar(ch, obj->affected[j].location, obj->affected[j].modifier, GET_OBJ_AFFECT(obj), TRUE); affect_total(ch); }
/* Remove an affected_type structure from a char (called when duration reaches * zero). Pointer *af must never be NIL! Frees mem and calls * affect_location_apply */ void affect_remove(struct char_data *ch, struct affected_type *af) { struct affected_type *temp; if (ch->affected == NULL) { core_dump(); return; } affect_modify_ar(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); }
/* start one char fighting another (yes, it is horrible, I know... ) */ void set_fighting(struct char_data *ch, struct char_data *vict) { if (ch == vict) return; if (FIGHTING(ch)) { core_dump(); return; } ch->next_fighting = combat_list; combat_list = ch; if (AFF_FLAGGED(ch, AFF_SLEEP)) affect_from_char(ch, SPELL_SLEEP); FIGHTING(ch) = vict; GET_POS(ch) = POS_FIGHTING; if (!pk_allowed) check_killer(ch, vict); }
/* Update PCs, NPCs, and objects */ void point_update(void) { struct char_data *i, *next_char; struct obj_data *j, *next_thing, *jj, *next_thing2; /* characters */ for (i = character_list; i; i = next_char) { next_char = i->next; gain_condition(i, FULL, -1); gain_condition(i, DRUNK, -1); gain_condition(i, THIRST, -1); if (GET_POS(i) >= POS_STUNNED) { GET_HIT(i) = MIN(GET_HIT(i) + hit_gain(i), GET_MAX_HIT(i)); GET_MANA(i) = MIN(GET_MANA(i) + mana_gain(i), GET_MAX_MANA(i)); GET_MOVE(i) = MIN(GET_MOVE(i) + move_gain(i), GET_MAX_MOVE(i)); if (AFF_FLAGGED(i, AFF_POISON)) if (damage(i, i, 2, SPELL_POISON) == -1) continue; /* Oops, they died. -gg 6/24/98 */ if (GET_POS(i) <= POS_STUNNED) update_pos(i); } else if (GET_POS(i) == POS_INCAP) { if (damage(i, i, 1, TYPE_SUFFERING) == -1) continue; } else if (GET_POS(i) == POS_MORTALLYW) { if (damage(i, i, 2, TYPE_SUFFERING) == -1) continue; } if (!IS_NPC(i)) { update_char_objects(i); if (GET_LEVEL(i) < idle_max_level) check_idling(i); } } /* objects */ for (j = object_list; j; j = next_thing) { next_thing = j->next; /* Next in object list */ /* If this is a corpse */ if (IS_CORPSE(j)) { /* timer count down */ if (GET_OBJ_TIMER(j) > 0) GET_OBJ_TIMER(j)--; if (!GET_OBJ_TIMER(j)) { if (j->carried_by) act("$p decays in your hands.", FALSE, j->carried_by, j, 0, TO_CHAR); else if ((IN_ROOM(j) != NOWHERE) && (world[IN_ROOM(j)].people)) { act("A quivering horde of maggots consumes $p.", TRUE, world[IN_ROOM(j)].people, j, 0, TO_ROOM); act("A quivering horde of maggots consumes $p.", TRUE, world[IN_ROOM(j)].people, j, 0, TO_CHAR); } for (jj = j->contains; jj; jj = next_thing2) { next_thing2 = jj->next_content; /* Next in inventory */ obj_from_obj(jj); if (j->in_obj) obj_to_obj(jj, j->in_obj); else if (j->carried_by) obj_to_room(jj, IN_ROOM(j->carried_by)); else if (IN_ROOM(j) != NOWHERE) obj_to_room(jj, IN_ROOM(j)); else core_dump(); } extract_obj(j); } } /* If the timer is set, count it down and at 0, try the trigger */ /* note to .rej hand-patchers: make this last in your point-update() */ else if (GET_OBJ_TIMER(j)>0) { GET_OBJ_TIMER(j)--; if (!GET_OBJ_TIMER(j)) timer_otrigger(j); } } }
int main(int argc, char **argv) { assert(HEAPSIZE < MAXSIZE_FILE); // otherwise config.h is screwed int i=0,rv=0; int first_byte=0,second_byte=0; FILE* infile = NULL; ramword_t *inputbuffer = NULL; stack_t* stack = NULL; ramaddr_t* heap = NULL; cpu_t* cpu = NULL; switch(argc) { case 0: printf("Unsuitable environment (argc==0)\n"); rv = -1; case 1: printf("Usage: emma input\n"); rv = -1; case 2: if((infile = fopen(argv[1],"r")) == NULL) { printf("[error] could not open input file, check permissions.\n"); rv = -1; } break; default: printf("Usage: emma input\n"); rv = -1; } // if we're successful, get on with the business of the day if(rv==0) { // initialize the CPU cpu = malloc(sizeof(cpu_t)); if(cpu == NULL) return -1; // error memset(cpu,0,sizeof(cpu_t)); if((inputbuffer = malloc(MAXSIZE_FILE * sizeof(*inputbuffer)))==NULL) return -1; stack = st_create(STACKSIZE); #ifdef EMMA_DEBUG fprintf(stderr,"HEAPSIZE: %d\n",HEAPSIZE); #endif heap = heap_init(HEAPSIZE); // read the file into memory (more complex than it first seemed) while(((first_byte = getc(infile)) != EOF)&&((second_byte = getc(infile)) != EOF)) { inputbuffer[i] = (first_byte<<8) | second_byte; i++; if(i>=MAXSIZE_FILE) break; // this fixes the cause of a segfault } #ifdef EMMA_DEBUG int j=0; printf("Loaded program: "); while(j<i) { printf("%.4X ",inputbuffer[j]); j++; } putchar('\n'); #endif // warn about program truncation if(i > HEAPSIZE) { #ifdef EMMA_DEBUG printf("Warning: input file \"%s\" has been truncated\n",argv[1]); #endif #ifdef FATAL_ERRORS rv = -1; #endif } // move the input buffer onto the heap at offset 0x0000, truncated to HEAPSIZE if(!heap_load(heap,inputbuffer,HEAPSIZE)) { #ifdef EMMA_DEBUG printf("Error: heap loading failed\n"); #endif #ifdef FATAL_ERRORS rv = -1; #endif } // the input buffer is no longer necessary, so we should free it free(inputbuffer); // set up the cpu with the stack and the heap cpu->stack = stack; cpu->pc = heap; if(rv==0) { // set the program running, return the state of the CPU at exit cpu = emu_run(cpu); } #ifdef EMMA_DEBUG if((cpu->flag_reg & FLAG_ERROR)!=0) // this if was previously backwards { printf("Program halted with error: %.2X\n",cpu->errno); core_dump(cpu); } #endif // shutdown safely (free any used memory) st_free(stack); heap_free(heap); free(cpu); fclose(infile); } return rv; }
/* * Remove an affected_type structure from a char (called when duration * reaches zero). Pointer *af must never be NIL! Frees mem and calls * affect_location_apply */ void affect_remove(struct char_data * ch, struct affected_type * af, int output) { struct affected_type *temp; struct affected_type aff; bool accum_affect = FALSE; int k; if (ch->affected == NULL) { core_dump(); return; } switch (af->type) { case SPELL_CHARM: { struct char_data* victim = ch->master; if (output == 0) break; affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); if (ch->master) { stop_follower(ch); } if (victim) { if(IS_NPC(ch)) { SET_BIT(MOB_FLAGS(ch), MOB_AGGRESSIVE | MOB_MEMORY); } if (mag_savingthrow(victim, SAVING_SPELL)) { hit(victim, ch, TYPE_UNDEFINED); } } return; } case SPELL_LIGHT: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light -= 10; } } break; case SPELL_DARKNESS: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light += 10; } } break; case SPELL_BLACK_PLAGUE: mag_affects(30, ch, ch, SPELL_BREATH_OF_LIFE, SAVING_SPELL); break; case SPELL_CALL_ANIMAL_SPIRIT: case SPELL_ANIMAL_SUMMONING: case SPELL_ANIMAL_SUMMONING_II: case SPELL_ANIMAL_SUMMONING_III: case SPELL_CONJURE_ELEMENTAL: case SPELL_GREATER_ELEMENTAL: case SPELL_DUST_DEVIL: case SPELL_STICKS_TO_SNAKES: case SPELL_SUMMON_INSECTS: case SPELL_AERIAL_SERVANT: case SPELL_SUMMON_GUARD: if (IS_NPC(ch)) { if (GET_POS(ch) > POS_DEAD) { if (output == 1) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); GET_NAME(ch, chname); stop_fighting(ch); /*Fighting Bug Fix Jasrags*/ sprintf(buf, "%s disappears into thin air as the summoning ends.", chname); act(buf, FALSE, world[ch->in_room].people, 0, 0, TO_ROOM); FREE_NAME(chname); extract_char(ch); ch = NULL; return; } } } break; case SPELL_POLYMORPH: if (!PRF_FLAGGED(ch, PRF_NOTSELF)) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); return; } break; case SPELL_DONTUSEME: if(AFF_FLAGGED(ch, AFF_STANCE) && !AFF_FLAGGED(ch, AFF_TIRED)) { aff.type = SKILL_STANCE; aff.duration = 2; aff.location = APPLY_STR; aff.modifier = -2; aff.bitvector = AFF_TIRED; accum_affect = FALSE; affect_to_char(ch, &aff); } break; default: break; } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type != SPELL_POLYMORPH && af->type != SPELL_DONTUSEME) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (*spell_wear_off_msg[af->type]) { send_to_char(spell_wear_off_msg[af->type], ch); send_to_char("\r\n", ch); } } } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type == SPELL_POLYMORPH) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (PLR_FLAGGED(ch, PLR_RABBIT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_RABBIT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing, and your ears shrinking. You no longer feel like a rabbit.\r\n", ch); act("$n's body grows, $s ears shrinking. $n no longer looks like a rabbit.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BIRD)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BIRD); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing and your feathers falling away. You no longer feel like a bird.\r\n", ch); act("$n's body grows, $s feathers falling away as it expands. $n no longer looks like a bird.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_WOLF)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_WOLF); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your your fur shed and your teeth shrink. You no longer feel like a wolf.\r\n", ch); act("$n's teeth shrink, $s fur shedding. $n no longer looks like a wolf.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BEAR)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BEAR); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("Your claws shrink as does the rest of your body. You no longer feel like a bear.\r\n", ch); act("$n's claws shrink as does the rest of $s body. $n no longer looks like a bear.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_CAT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_CAT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your body growing, and your fur shedding. You no longer feel like a cat.\r\n", ch); act("$n's body slowly grows, $s fur shedding. $n no longer looks like a cat.\r\n", 0, ch, 0, 0, TO_ROOM); } for (k = 0; k < NUM_WEARS; k++) if (GET_EQ(ch, k)){ GET_OBJ_DISGUISE(GET_EQ(ch, k)) = 0; } } } affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); }
RETSIGTYPE usrsig(int sig) { core_dump(); }
/* * void store_mail(long #1, long #2, char * #3) * #1 - id number of the person to mail to. * #2 - id number of the person the mail is from. * #3 - The actual message to send. * * call store_mail to store mail. (hard, huh? :-) ) Pass 3 arguments: * who the mail is to (long), who it's from (long), and a pointer to the * actual message text (char *). */ void store_mail (long to, long from, char *message_pointer) { header_block_type header; data_block_type data; long last_address, target_address; char *msg_txt = message_pointer; int bytes_written, total_length = strlen (message_pointer); if ((sizeof (header_block_type) != sizeof (data_block_type)) || (sizeof (header_block_type) != BLOCK_SIZE)) { core_dump (); return; } if (from < 0 || to < 0 || !*message_pointer) { log ("SYSERR: Mail system -- non-fatal error #5. (from == %ld, to == %ld)", from, to); return; } memset ((char *) &header, 0, sizeof (header)); /* clear the record */ header.block_type = HEADER_BLOCK; header.header_data.next_block = LAST_BLOCK; header.header_data.from = from; header.header_data.to = to; header.header_data.mail_time = time (0); strncpy (header.txt, msg_txt, HEADER_BLOCK_DATASIZE); header.txt[HEADER_BLOCK_DATASIZE] = '\0'; target_address = pop_free_list (); /* find next free block */ index_mail (to, target_address); /* add it to mail index in memory */ write_to_file (&header, BLOCK_SIZE, target_address); if (strlen (msg_txt) <= HEADER_BLOCK_DATASIZE) return; /* that was the whole message */ bytes_written = HEADER_BLOCK_DATASIZE; msg_txt += HEADER_BLOCK_DATASIZE; /* move pointer to next bit of text */ /* * find the next block address, then rewrite the header to reflect where * the next block is. */ last_address = target_address; target_address = pop_free_list (); header.header_data.next_block = target_address; write_to_file (&header, BLOCK_SIZE, last_address); /* now write the current data block */ memset ((char *) &data, 0, sizeof (data)); /* clear the record */ data.block_type = LAST_BLOCK; strncpy (data.txt, msg_txt, DATA_BLOCK_DATASIZE); data.txt[DATA_BLOCK_DATASIZE] = '\0'; write_to_file (&data, BLOCK_SIZE, target_address); bytes_written += strlen (data.txt); msg_txt += strlen (data.txt); /* * if, after 1 header block and 1 data block there is STILL part of the * message left to write to the file, keep writing the new data blocks and * rewriting the old data blocks to reflect where the next block is. Yes, * this is kind of a hack, but if the block size is big enough it won't * matter anyway. Hopefully, MUD players won't pour their life stories out * into the Mud Mail System anyway. * * Note that the block_type data field in data blocks is either a number >=0, * meaning a link to the next block, or LAST_BLOCK flag (-2) meaning the * last block in the current message. This works much like DOS' FAT. */ while (bytes_written < total_length) { last_address = target_address; target_address = pop_free_list (); /* rewrite the previous block to link it to the next */ data.block_type = target_address; write_to_file (&data, BLOCK_SIZE, last_address); /* now write the next block, assuming it's the last. */ data.block_type = LAST_BLOCK; strncpy (data.txt, msg_txt, DATA_BLOCK_DATASIZE); data.txt[DATA_BLOCK_DATASIZE] = '\0'; write_to_file (&data, BLOCK_SIZE, target_address); bytes_written += strlen (data.txt); msg_txt += strlen (data.txt); } } /* store mail */