示例#1
0
// Fetch and return the next char from input stream.
void fetchc(void) {
	// terrible horrible eeprom addressing kludge
	if (isram(fetchptr)) {
		if (*fetchptr) fetchptr++;
		inchar = *fetchptr;
	} 
	else {	// fetch char from eeprom
		int addr = dekludge(fetchptr);
		inchar = eeread(addr);
		if ((inchar != 0) && (inchar != 255)) {
			inchar = eeread(++addr);
			fetchptr = kludge(addr);		// save incremented pointer
			if (inchar == 255) inchar = 0;
		}
	}

#ifdef PARSER_TRACE
	// char trace
	if (trace) {
		//spb('['); printInteger(inchar);spb(':'); if (inchar) spb(inchar); spb(']');
		spb('[');
		if (inchar >= 0x20) spb(inchar);
		else { spb('\\'); printInteger(inchar); }
		spb(']');
	}
#endif

	//return inchar;
}
示例#2
0
void prompt(void) {
char buf[IDLEN+1];
	// Run the script named "prompt" if there is one else print "> "
	strncpy_P(buf, getmsg(M_promptid), IDLEN);	// get the name "prompt" in our cmd buf
	int entry = findKey(buf);
	if (entry >= 0) doCommand(kludge(findend(entry)));
	else msgp(M_prompt);							// else print default prompt
}
示例#3
0
void justswld(struct monst *mtmp, char *name)
{
    mtmp->mx = u.ux;
    mtmp->my = u.uy;
    u.ustuck = mtmp;
    pmon(mtmp);
    kludge("%s swallows you!", name);
    more();
    seeoff(1);
    u.uswallow = 1;
    swallowed();
}
示例#4
0
void youswld(struct monst *mtmp, int dam, int die, char *name)
{
    if(mtmp != u.ustuck) {
        return;
    }
    
    kludge("%s digests you!", name);
    u.uhp -= dam;

    if(u.uswldtim == die) {
        ++u.uswldtim;
        pline("It totally digests you!");
        u.uhp = -1;
    }
    ++u.uswldtim;

    if(u.uhp < 1) {
        done_in_by(mtmp);
    }
}
// Get a statement
void getstatement(void) {

#if !defined(TINY85)
	chkbreak();
#endif

	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		char *fetchmark = fetchptr;
		for (;;) {
			fetchptr = fetchmark;			// restore to mark
			primec();						// set up for mr. getsym()
			getsym(); 						// fetch the start of the conditional
			if (!getnum()) {					
				//longjmp(env, X_EXIT);		// get the conditional; exit on false
				sym = s_eof;				// we're finished here.  move along.
				return;
			}
			if (sym != s_colon) expectedchar(':');
			getsym();	// eat :
			getstatementlist();
		}
	}
	
	else if (sym == s_if) {
		getsym(); 								// fetch the start of the conditional
		if (!getnum()) {
			//longjmp(env, X_EXIT);	// get the conditional; exit on false
			sym = s_eof;
			return;
		}
		if (sym != s_colon) expectedchar(':');
		getsym();	// eat :
		getstatementlist();
	}


#if SKETCH
	// The switch statement: call one of N macros based on a selector value
	// switch <numval>: macroid1, macroid2,.., macroidN
	// numval < 0: numval = 0
	// numval > N: numval = N

	else if (sym == s_switch) {
		getsym();	// eat "switch"
		numvar selector = getnum();	// evaluate the switch value
		if (selector < 0) selector = 0;
		if (sym != s_colon) expectedchar(':');

		// we sit before the first macroid
		// scan and discard the <selector>'s worth of macro ids 
		// that sit before the one we want
		for (;;) {
			getsym();	// get an id, sets symval to its eeprom addr as a side effect
			if (sym != s_macro) expected (6);		// TODO: define M_macro instead of 6
			getsym();	// eat id, get separator; assume symval is untouched
			if ((sym == s_semi) || (sym == s_eof)) break;	// last case is default so we exit always
			if (sym != s_comma) expectedchar(',');
			if (!selector) break;		// ok, this is the one we want to execute
			selector--;					// one down...
		}

		// call the macro whose addr is squirreled in symval all this time
		// on return, the parser is ready to pick up where we left off
		doMacroCall(symval);

		// scan past the rest of the unused switch options, if any
		// TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space
		while ((sym != s_semi) && (sym != s_eof)) getsym();		// scan to end of statement without executing
	}
#endif


	else if ((sym == s_macro) || (sym == s_undef)) {		// macro def or ref
		getsym();						// scan past macro name to next symbol: ; or :=
		if (sym == s_define) {			// macro definition: macroid := strvalue
			// to define the macro, we need to copy the id somewhere on the stack
			// to avoid having this local buffer in every getstatement stack frame,
			// we break out defineMacro here to a separate function that only eats that
			// stack in the case that a macro is being defined
#ifdef TINY85
			unexpected(M_defmacro);
#else
			defineMacro();
#endif
		}
		else if ((sym == s_semi) || (sym == s_eof)) {	// valid macro reference: let's call it
#if SKETCH
			doMacroCall(symval);			// parseid stashes the macro address in symval
#else
			char op = sym;					// save sym for restore
			expval = findKey(idbuf);		// assumes id in idbuf isn't clobbered since getsym() above
			if (expval >= 0) {
				char *fetchmark = fetchptr;			// save the current parse pointer

				// call the macro
				calleeprommacro(findend(expval));	// register the macro into the parser stream
				getsym();
				getstatementlist();		// parse and execute the macro code here
				if (sym != s_eof) expected(M_eof);

				// restore parsing context so we can resume cleanly
				fetchptr = fetchmark;	// restore pointer
				primec();				// and inchar
				sym = op;				// restore saved sym: s_semi or s_eof
			} else unexpected(M_id);
#endif
		}
		else expectedchar(';');
		//else getexpression();		// assume it was macro1+32+macro2...
	}
	
	else if (sym == s_run) {	// run macroname
		getsym();
		if (sym != s_macro) unexpected(M_id);

#if 0
		// address of macroid is in symval via parseid
		startTask(kludge(symval));
		getsym();
#else
		// address of macroid is in symval via parseid
		// check for [,snoozeintervalms]
		getsym();	// eat macroid to check for comma; symval untouched
		if (sym == s_comma) {
			vpush(symval);
			getsym();			// eat the comma
			getnum();			// get a number or else
			startTask(kludge(vpop()), expval);
		}
		else startTask(kludge(symval), 0);
#endif
	}
	else if (sym == s_stop) {
		getsym();
		if (sym == s_mul) {						// stop * stops all tasks
			initTaskList();
			getsym();
		}
		else if ((sym == s_semi) || (sym == s_eof)) {
			if (background) stopTask(curtask);	// stop with no args stops the current task IF we're in back
			else initTaskList();				// in foreground, stop all
		}
		else stopTask(getnum());
	}

	else if (sym == s_boot) reboot();

#if !defined(TINY85)
	else if (sym == s_rm) {		// rm "sym" or rm *
		getsym();
		if (sym == s_macro) {
			eraseentry(idbuf);
		} 
		else if (sym == s_mul) nukeeeprom();
		else expected(M_id);
		getsym();
	}
	else if (sym == s_ps) showTaskList();
	else if (sym == s_peep) 	{ getsym(); cmd_peep(); }
	else if (sym == s_ls) 		{ getsym(); cmd_ls(); }
	else if (sym == s_help) 	{ getsym(); cmd_help(); }
	else if (sym == s_print) 	{ getsym(); cmd_print(); }
#endif

#ifdef HEX_UPLOAD
	// a line beginning with a colon is treated as a hex record
	// containing data to upload to eeprom
	//
	// TODO: verify checksum
	//
	else if (sym == s_colon) {
		// fetchptr points at the byte count
		byte byteCount = gethex(2);		// 2 bytes byte count
		int addr = gethex(4);			// 4 bytes address
		byte recordType = gethex(2);	// 2 bytes record type; now fetchptr -> data
		if (recordType == 1) reboot();	// reboot on EOF record (01)
		if (recordType != 0) return;	// we only handle the data record (00)
		if (addr == 0) nukeeeprom();	// auto-clear eeprom on write to 0000
		while (byteCount--) eewrite(addr++, gethex(2));		// update the eeprom
		gethex(2);						// discard the checksum
		getsym();						// and re-prime the parser
	}
#endif

	else  {
		getexpression();
	}
}
// Get a statement
numvar getstatement(void) {
numvar retval = 0;
char *fetchmark;

	chkbreak();

//#define LINEMODE
#ifdef LINEMODE
	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		char *fetchmark = fetchptr;
		for (;;) {
			fetchptr = fetchmark;			// restore to mark
			primec();						// set up for mr. getsym()
			getsym(); 						// fetch the start of the conditional
			if (!getnum()) {					
				//longjmp(env, X_EXIT);		// get the conditional; exit on false
				sym = s_eof;				// we're finished here.  move along.
				return;
			}
			if (sym != s_colon) expectedchar(':');
			getsym();	// eat :
			getstatementlist();
		}
	}
	else if (sym == s_if) {
		getsym(); 								// fetch the start of the conditional
		if (!getnum()) {
			//longjmp(env, X_EXIT);	// get the conditional; exit on false
			sym = s_eof;
			return;
		}
		if (sym != s_colon) expectedchar(':');
		getsym();	// eat :
		getstatementlist();
	}

	// The switch statement: call one of N macros based on a selector value
	// switch <numval>: macroid1, macroid2,.., macroidN
	// numval < 0: numval = 0
	// numval > N: numval = N

	else if (sym == s_switch) {
		getsym();	// eat "switch"
		numvar selector = getnum();	// evaluate the switch value
		if (selector < 0) selector = 0;
		if (sym != s_colon) expectedchar(':');

		// we sit before the first macroid
		// scan and discard the <selector>'s worth of macro ids 
		// that sit before the one we want
		for (;;) {
			getsym();	// get an id, sets symval to its eeprom addr as a side effect
			if (sym != s_macro) expected (6);		// TODO: define M_macro instead of 6
			getsym();	// eat id, get separator; assume symval is untouched
			if ((sym == s_semi) || (sym == s_eof)) break;	// last case is default so we exit always
			if (sym != s_comma) expectedchar(',');
			if (!selector) break;		// ok, this is the one we want to execute
			selector--;					// one down...
		}

		// call the macro whose addr is squirreled in symval all this time
		// on return, the parser is ready to pick up where we left off
		domacrocall(symval);

		// scan past the rest of the unused switch options, if any
		// TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space
		while ((sym != s_semi) && (sym != s_eof)) getsym();		// scan to end of statement without executing
	}

#else
	// new statement handling
	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		fetchmark = fetchptr;
		for (;;) {
			fetchptr = fetchmark;			// restore to mark
			primec();						// set up for mr. getsym()
			getsym(); 						// fetch the start of the conditional
			if (getnum()) {
				retval = getstatement();
				if (sym == s_returning) break;	// exit if we caught a return
			}
			else {
				skipstatement();
				break;
			}
		}
	}
	
	else if (sym == s_if) {
		getsym();			// eat "if"
		if (getnum()) {
			retval = getstatement();
			if (sym == s_else) {
				getsym();	// eat "else"
				skipstatement();
			}
		} else {
			skipstatement();
			if (sym == s_else) {
				getsym();	// eat "else"
				retval = getstatement();
			}
		}
	}
	else if (sym == s_lcurly) {
		getsym(); 	// eat "{"
		while ((sym != s_eof) && (sym != s_returning) && (sym != s_rcurly)) retval = getstatement();
		if (sym == s_rcurly) getsym();	// eat "}"
	}
	else if (sym == s_return) {
		getsym();	// eat "return"
		if ((sym != s_eof) && (sym != s_semi)) retval = getnum();
		sym = s_returning;		// signal we're returning up the line
	}
	else if (sym == s_switch) retval = getswitchstatement();

	else if (sym == s_function) cmd_function();

#endif


	else if (sym == s_run) {	// run macroname
		getsym();
		if (sym != s_macro) unexpected(M_id);

		// address of macroid is in symval via parseid
		// check for [,snoozeintervalms]
		getsym();	// eat macroid to check for comma; symval untouched
		if (sym == s_comma) {
			vpush(symval);
			getsym();			// eat the comma
			getnum();			// get a number or else
			startTask(kludge(vpop()), expval);
		}
		else startTask(kludge(symval), 0);
	}

	else if (sym == s_stop) {
		getsym();
		if (sym == s_mul) {						// stop * stops all tasks
			initTaskList();
			getsym();
		}
		else if ((sym == s_semi) || (sym == s_eof)) {
			if (background) stopTask(curtask);	// stop with no args stops the current task IF we're in back
			else initTaskList();				// in foreground, stop all
		}
		else stopTask(getnum());
	}

	else if (sym == s_boot) reboot();

#if !defined(TINY85)
	else if (sym == s_rm) {		// rm "sym" or rm *
		getsym();
		if (sym == s_macro) {
			eraseentry(idbuf);
		} 
		else if (sym == s_mul) nukeeeprom();
		else if (sym != s_undef) expected(M_id);
		getsym();
	}
	else if (sym == s_ps) 		{ getsym();	showTaskList(); }
	else if (sym == s_peep) 	{ getsym(); cmd_peep(); }
	else if (sym == s_ls) 		{ getsym(); cmd_ls(); }
	else if (sym == s_help) 	{ getsym(); cmd_help(); }
	else if (sym == s_print) 	{ getsym(); cmd_print(); }
	else if (sym == s_semi)		{ ; }	// ;)
#endif

#ifdef HEX_UPLOAD
	// a line beginning with a colon is treated as a hex record
	// containing data to upload to eeprom
	//
	// TODO: verify checksum
	//
	else if (sym == s_colon) {
		// fetchptr points at the byte count
		byte byteCount = gethex(2);		// 2 bytes byte count
		int addr = gethex(4);			// 4 bytes address
		byte recordType = gethex(2);	// 2 bytes record type; now fetchptr -> data
		if (recordType == 1) reboot();	// reboot on EOF record (01)
		if (recordType != 0) return;	// we only handle the data record (00)
		if (addr == 0) nukeeeprom();	// auto-clear eeprom on write to 0000
		while (byteCount--) eewrite(addr++, gethex(2));		// update the eeprom
		gethex(2);						// discard the checksum
		getsym();						// and re-prime the parser
	}
#endif

	else getexpression();

	if (sym == s_semi) getsym();		// eat trailing ';'
	return retval;
}
示例#7
0
// call macro in eeprom
void calleeprommacro(int macrotext) {
	// terrible horrible eeprom kludge
	//callmacro(kludge(macrotext));
	fetchptr = kludge(macrotext);
	primec();
}
示例#8
0
/*
 * mhitu: monster hits you
 *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
 */
bool
mhitu(struct monst *mtmp)
{
	struct permonst *mdat = mtmp->data;
	int tmp, ctmp;

	nomul(0);

	/* If swallowed, can only be affected by hissers and by u.ustuck */
	if (u.uswallow) {
		if (mtmp != u.ustuck) {
			if (mdat->mlet == 'c' && !rn2(13)) {
				pline("Outside, you hear %s's hissing!",
				      monnam(mtmp));
				pline("%s gets turned to stone!",
				      Monnam(u.ustuck));
				pline("And the same fate befalls you.");
				done_in_by(mtmp);
				/* "notreached": not return(1); */
			}
			return (0);
		}
		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
		case ',':
			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
				5, "The trapper");
			break;
		case '\'':
			youswld(mtmp, rnd(6), 7, "The lurker above");
			break;
		case 'P':
			youswld(mtmp, d(2, 4), 12, "The purple worm");
			break;
		default:
			/* This is not impossible! */
			pline("The mysterious monster totally digests you.");
			u.uhp = 0;
		}
		if (u.uhp < 1)
			done_in_by(mtmp);
		return (0);
	}

	if (mdat->mlet == 'c' && Stoned)
		return (0);

	/* make eels visible the moment they hit/miss us */
	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
		mtmp->minvis = 0;
		pmon(mtmp);
	}
	if (!strchr("1&DuxynNF", mdat->mlet))
		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
	else
		tmp = 0;
	if (strchr(UNDEAD, mdat->mlet) && midnight())
		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));

	ctmp = tmp && !mtmp->mcan &&
	    (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
	switch (mdat->mlet) {
	case '1':
		if (wiz_hit(mtmp))	/* he disappeared */
			return (1);
		break;
	case '&':
		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
			makemon(PM_DEMON, u.ux, u.uy);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rn1(4, 2));
		}
		break;
	case ',':
		if (tmp)
			justswld(mtmp, "The trapper");
		break;
	case '\'':
		if (tmp)
			justswld(mtmp, "The lurker above");
		break;
	case ';':
		if (ctmp) {
			if (!u.ustuck && !rn2(10)) {
				pline("%s swings itself around you!",
				      Monnam(mtmp));
				u.ustuck = mtmp;
			} else if (u.ustuck == mtmp &&
				   levl[mtmp->mx][mtmp->my].typ == POOL) {
				pline("%s drowns you ...", Monnam(mtmp));
				done("drowned");
			}
		}
		break;
	case 'A':
		if (ctmp && rn2(2)) {
			if (Poison_resistance)
				pline("The sting doesn't seem to affect you.");
			else {
				pline("You feel weaker!");
				losestr(1);
			}
		}
		break;
	case 'C':
		hitu(mtmp, rnd(6));
		break;
	case 'c':
		if (!rn2(5)) {
			pline("You hear %s's hissing!", monnam(mtmp));
			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
			    && !carrying(DEAD_LIZARD)))
				Stoned = 5;
		}
		break;
	case 'D':
		if (rn2(6) || mtmp->mcan) {
			hitu(mtmp, d(3, 10));
			hitu(mtmp, rnd(8));
			hitu(mtmp, rnd(8));
			break;
		}
		kludge("%s breathes fire!", "The dragon");
		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
		break;
	case 'd':
		hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
		break;
	case 'e':
		hitu(mtmp, d(3, 6));
		break;
	case 'F':
		if (mtmp->mcan)
			break;
		kludge("%s explodes!", "The freezing sphere");
		if (Cold_resistance)
			pline("You don't seem affected by it.");
		else {
			xchar dn;
			if (17 - (u.ulevel / 2) > rnd(20)) {
				pline("You get blasted!");
				dn = 6;
			} else {
				pline("You duck the blast...");
				dn = 3;
			}
			losehp_m(d(dn, 6), mtmp);
		}
		mondead(mtmp);
		return (1);
	case 'g':
		if (ctmp && multi >= 0 && !rn2(3)) {
			kludge("You are frozen by %ss juices", "the cube'");
			nomul(-rnd(10));
		}
		break;
	case 'h':
		if (ctmp && multi >= 0 && !rn2(5)) {
			nomul(-rnd(10));
			kludge("You are put to sleep by %ss bite!",
			       "the homunculus'");
		}
		break;
	case 'j':
		tmp = hitu(mtmp, rnd(3));
		tmp &= hitu(mtmp, rnd(3));
		if (tmp) {
			hitu(mtmp, rnd(4));
			hitu(mtmp, rnd(4));
		}
		break;
	case 'k':
		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp)
			poisoned("bee's sting", mdat->mname);
		break;
	case 'L':
		if (tmp)
			stealgold(mtmp);
		break;
	case 'N':
		if (mtmp->mcan && !Blind) {
			pline("%s tries to seduce you, but you seem not interested.",
			    Amonnam(mtmp, "plain"));
			if (rn2(3))
				rloc(mtmp);
		} else if (steal(mtmp)) {
			rloc(mtmp);
			mtmp->mflee = 1;
		}
		break;
	case 'n':
		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
			pline("%s hits! (I hope you don't mind)",
			      Monnam(mtmp));
			u.uhp += rnd(7);
			if (!rn2(7))
				u.uhpmax++;
			if (u.uhp > u.uhpmax)
				u.uhp = u.uhpmax;
			flags.botl = 1;
			if (!rn2(50))
				rloc(mtmp);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
		}
		break;
	case 'o':
		tmp = hitu(mtmp, rnd(6));
		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
		    !u.ustuck && rn2(2)) {
			u.ustuck = mtmp;
			kludge("%s has grabbed you!", "The owlbear");
			u.uhp -= d(2, 8);
		} else if (u.ustuck == mtmp) {
			u.uhp -= d(2, 8);
			pline("You are being crushed.");
		}
		break;
	case 'P':
		if (ctmp && !rn2(4))
			justswld(mtmp, "The purple worm");
		else
			hitu(mtmp, d(2, 4));
		break;
	case 'Q':
		hitu(mtmp, rnd(2));
		hitu(mtmp, rnd(2));
		break;
	case 'R':
		if (tmp && uarmh && !uarmh->rustfree &&
		    (int)uarmh->spe >= -1) {
			pline("Your helmet rusts!");
			uarmh->spe--;
		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
		    uarm->otyp < STUDDED_LEATHER_ARMOR &&
		    (int)uarm->spe >= -1) {
			pline("Your armor rusts!");
			uarm->spe--;
		}
		break;
	case 'S':
		if (ctmp && !rn2(8))
			poisoned("snake's bite", mdat->mname);
		break;
	case 's':
		if (tmp && !rn2(8))
			poisoned("scorpion's sting", mdat->mname);
		hitu(mtmp, rnd(8));
		hitu(mtmp, rnd(8));
		break;
	case 'T':
		hitu(mtmp, rnd(6));
		hitu(mtmp, rnd(6));
		break;
	case 't':
		if (!rn2(5))
			rloc(mtmp);
		break;
	case 'u':
		mtmp->mflee = 1;
		break;
	case 'U':
		hitu(mtmp, d(3, 4));
		hitu(mtmp, d(3, 4));
		break;
	case 'v':
		if (ctmp && !u.ustuck)
			u.ustuck = mtmp;
		break;
	case 'V':
		if (tmp)
			u.uhp -= 4;
		if (ctmp)
			losexp();
		break;
	case 'W':
		if (ctmp)
			losexp();
		break;
#ifndef NOWORM
	case 'w':
		if (tmp)
			wormhit(mtmp);
#endif /* NOWORM */
		break;
	case 'X':
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		break;
	case 'x':
		{
			long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
			pline("%s pricks in your %s leg!",
			    Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
			set_wounded_legs(side, rnd(50));
			losehp_m(2, mtmp);
			break;
		}
	case 'y':
		if (mtmp->mcan)
			break;
		mondead(mtmp);
		if (!Blind) {
			pline("You are blinded by a blast of light!");
			Blind = d(4, 12);
			seeoff(0);
		}
		return (1);
	case 'Y':
		hitu(mtmp, rnd(6));
		break;
	}
	if (u.uhp < 1)
		done_in_by(mtmp);
	return (0);
}