mud/help/
mud/items/
mud/map/
mud/monsters/
mud/players/
sub update{
#$time=time;
my $time=$lastupdate;
until($time>time) {
	if (defined($do{$time})){
	#	print "aaaa!\n";
		while (@{$do{$time}}){
			print "@{$do{$time}[0]{args}}\n";
			&{$do{$time}[0]{sub}}(@{$do{$time}[0]{args}});
			shift @{$do{$time}};
			}
		}
	$time++;
	}
if (time-$mediumupdate>30){
	print ".";
	$mediumupdate=time;
	&mediumupdate;
	}

if (time-$longupdate>300){
	print "-";
	$longupdate=time;
	&longupdate;
	}
	
foreach $a (keys %outbuffer) {
	if (defined($user{$a}{monster})){
		local $incoming;
		$incoming=$outbuffer{$a};
		delete $outbuffer{$a};
		local $client=$a;
		if (defined(&{$monster[$user{$a}{monster}]{script}})){
			&{$monster[$user{$a}{"monster"}]{script}};
			}
		}
	}
foreach $a (keys %user){
	if ($user{$a}{round}){
		$user{$a}{round}--;
		}
	if ($user{$a}{stun}){
		$user{$a}{stun}--;
		}
	if($user{$a}{dead}){
		if (time-$user{$a}{dead}>10){
			if (defined($user{$a}{monster})){
				#monster is dead
				print "monster $user{$a}{name} should decay\n";
				say("the dead body of $user{$a}{name} decays into nothingness.",$user{$a}{room});
				monsterdecay($a);
				next;
				}
			else {
				print "player $user{$a}{name} should pass away\n";
				playerdecay($a);
				#player is dead
				next;
				}
			}
		}
	foreach $b (keys %{$user{$a}{exp}}){
		foreach $c (keys %{$user{$a}{exp}{$b}}){
			if ($user{$a}{exp}{$b}{$c}{pool}>0){
		#		print "c\n";
				my $increase=0;
				if ($user{$a}{exp}{$b}{$c}{pool}>($user{$a}{disc}*100)){
					$increase=int($user{$a}{wis}/5);
					}
				elsif ($user{$a}{exp}{$b}{$c}{pool}>300){
				#	print "e\n";
					$increase=$user{$a}{wis}+(int(($user{$a}{exp}{$b}{$c}{pool}-300)/300)*3);
					}
				else {
			#		print "x\n";
					$increase=int($user{$a}{wis}/5);
					}
		#		print "increase=$increase\n\n";
				if ($user{$a}{exp}{$b}{$c}{pool}>=$increase){
					$user{$a}{exp}{$b}{$c}{pool}-=$increase;
					$user{$a}{exp}{$b}{$c}{expcur}+=$increase;
					}
				else {
					$user{$a}{exp}{$b}{$c}{expcur}+=$user{$a}{exp}{$b}{$c}{pool};
					$user{$a}{exp}{$b}{$c}{pool}=0;
					}
				my $ranks=0;
				while ($user{$a}{exp}{$b}{$c}{expcur}>=$user{$a}{exp}{$b}{$c}{expneeded}){
					print "cur=$user{$a}{exp}{$b}{$c}{expcur}\n$c\n$b\n";
					print keys %{$user{$a}{exp}{$b}{$c}};
					my $d=$user{$a}{exp}{$b}{$c}{expcur}-$user{$a}{exp}{$b}{$c}{expneeded};
					$user{$a}{exp}{$b}{$c}{ranks}+=1;
				$ranks++;	$user{$a}{exp}{$b}{$c}{expneeded}=($user{$a}{exp}{$b}{$c}{ranks}*$user{$a}{exp}{$b}{$c}{ranks})*100;
						$user{$a}{exp}{$b}{$c}{expcur}=$d;
					}
				if ($ranks==1){
					$outbuffer{$a}.="\r\nYou earn a rank of $c \r\n$prompt";
					}
				elsif ($ranks>1){
					$outbuffer{$a}.="\r\nYou earn $ranks ranks of $c\r\n$prompt";
					
					}
				}
			}
		}
	}
}
sub mediumupdate {
print ".";
foreach $a (keys %user){
	unless (defined ($user{$a}{vitality})){
		next;
		}
	$user{$a}{vitality}+=$user{$a}{con};
	if ($user{$a}{vitality}>$user{$a}{vitalitymax}){
		$user{$a}{vitality}=$user{$a}{vitalitymax}
		}
	foreach $b (keys %{$user{$a}{health}}){
		if (defined($user{$a}{health}{$b}{requires})){
			my $c=$user{$a}{health}{$b}{requires};
			if ($user{$a}{health}{$c}{hp}<=0){
				next;
				}
			}
		if ($user{$a}{health}{$b}{bleeding}){
#			print "doing $user{$a}{health}{$b}{bleeding} bleeding damage from $user{$a}{vitality}\n";
			$user{$a}{vitality}-=$user{$a}{health}{$b}{bleeding}
			}
		if ($user{$a}{health}{$b}{intbleeding}){
	#		print "doing $user{$a}{health}{$b}{intbleeding} intbleeding damage from $user{$a}{vitality}\n";
			$user{$a}{vitality}-=$user{$a}{health}{$b}{intbleeding}
			}
		
		#print "$b-$user{$a}{health}{$b}{bleeding}-$user{$a}{health}{$b}{intbleeding}--";
		}
	if ($user{$a}{vitality}<=0 and (!$user{$a}{dead})){
		#print "$user{$a}{vitality}\n";
		died($a);
		}
	}

}
sub longupdate {
foreach $node (@node){
	$a=rand(10);
	if (${$node}{max}>${$node}{maxused}){
		if ($a<${$node}{prob}){
			#print"a\n";
			${$node}{maxused}++;
			my $d=int(rand(@{${$node}{monsters}}));
			#print "d=$d\n";
			createmonster(${$node}{monsters}[$d],${$node}{room},$node);
			}
		}
	}
foreach $a ($select->handles){
#only checking actual people, monsters can't be inactive after all.
	unless (defined($user{$a})){
		#don't ask me why but there is one in here thats not a person. so we skip it.
		next;
		}
	unless (defined($user{$a}{name})){
		next;
		}
	if (defined($last{$a}) and (time-$last{$a}>500)){
		$outbuffer{$a}.="You have been inactive for too long.\r\n$prompt";
		}
	if (defined($last{$a}) and (time-$last{$a}>600)){
		print "removing $a for inactivity\n";
		&delete($a);
		next;
		}
	}

}
sub createmonster {
$mon=shift;
$room=shift;
$node=shift;
unless(defined($monster[$mon])){
	return;
	}
print "creating a $monster[$mon]{name} monster\n";
local $client="monster".$monstertotal++;
unless (loadplayer($monster[$mon]{name}, $client, "monsters")){
	print "Error\r\n";
	}
my $z=int(rand(@{$monster[$mon]{adjectives}}));
$user{$client}{monster}=$mon;
$user{$client}{node}=$node;
$user{$client}{room}=$room;
$user{$client}{desc}=$monster[$mon]{desc};
$outbuffer{$client}.="Welcome to the world.\n";
$user{$client}{name}=$monster[$mon]{adjectives}[$z]." $monster[$mon]{name}";
$user{$client}{pre}=$monster[$mon]{pre};
$room[$user{$client}{room}]{in}{$client}=$user{$client}{name};
if (defined($monster[$mon]{birthline})){
	my $a=$monster[$mon]{birthline};
	$a=~s/\[(.*?)\]/$user{$client}{$1}/isg;
	say("$a");
	}
else {
	say("$user{$client}{name} suddenly spawns before your eyes.");
}
my $time=time;
if (defined($monster[$mon]{scriptbirth})){
	&{$monster[$mon]{scriptbirth}};
	}
#push (@{$do{$time+10}},{sub=>"say", args=>["hello","$user{$client}{room}"]})
}
sub addexp {
my $skill=shift;
my $skilltype=shift;
my $amount=shift;
my $client=(shift or $client);
unless($client){
	my $client=shift;
	}
unless ($skilltype and $amount and $skill){
	return;
	}
unless ($user{$client}){
	print "error with adding exp, no user{client}\n\n";
	return;
	}
unless (defined($user{$client}{exp}{$skilltype})){
	#print "zzz\n";
	$user{$client}{exp}{$skilltype}={total=>0};
	}
unless(defined($user{$client}{exp}{$skilltype}{$skill})){
print "AZXCD\n";
	$user{$client}{exp}{$skilltype}{$skill}={pool=>0,ranks=>0,expcur=>0,expneeded=>50};
	}
my $maxpool=$user{$client}{disc}*100;
if ($user{$client}{exp}{$skilltype}{$skill}{pool}>=$maxpool){
	$outbuffer{$client}.="Your head aches from absorbing $skill and you learn very little\r\n$prompt";
	$user{$client}{exp}{$skilltype}{$skill}{pool}+=$amount/100;
	return 0;
	}
$user{$client}{exp}{$skilltype}{$skill}{pool}+=$amount;
if ($user{$client}{exp}{$skilltype}{$skill}{pool}>=$maxpool){
	$outbuffer{$client}.="Your head begins to hurt from absorbing $skill and you learn very little\r\n$prompt";
	}
}
sub died {
my $dead=shift;
print "$user{$dead}{name} has died!!!\n";
say2("$user{$dead}{name} falls dead",$user{$dead}{room},"You fall to the ground dead",$dead);
$user{$dead}{dead}=time;
$user{$dead}{position}="lying";
$user{$dead}{roomdesc}="the dead body of $user{$dead}{name} lies here";
$type{$dead}="dead";
}
sub say {
$message=shift;
my $room=(shift or $user{$client}{room});
foreach $a (keys %{$room[$room]{in}}){
	$outbuffer{$a}.="$message\r\n$prompt";
	}
}
sub say2 {
$message=shift;
$room=shift;
$message2=shift;
$ignore=shift;
foreach $a (keys %{$room[$room]{in}}){
#print "$a\n";
	if ($a eq "$ignore"){
		if ($message2){
			$outbuffer{$a}.="$message2\r\n$prompt";
			}
		}
	else {
	$outbuffer{$a}.="$message\r\n$prompt";
		}
	}

}
sub look{
if (defined($user{$client}{brief})){
	$outbuffer{$client}.="$room[$user{$client}{room}]{shortdesc}\r\n";
	}
else{
	$outbuffer{$client}.="$room[$user{$client}{room}]{longdesc}\r\n";
	}
local $b=0;
foreach $a (keys %{$room[$user{$client}{room}]{in}}){
	if (defined($user{$a}{hiding})){
		next;
		}
	unless ($room[$user{$client}{room}]{in}{$a} eq "$user{$client}{name}"){
		unless($b==1){
			$b=1;
			if ($user{$a}{roomdesc}){
				$outbuffer{$client}.= "Also here is : $user{$a}{roomdesc}";
				}
			else {
				$outbuffer{$client}.= "Also here is : $user{$a}{pre}$room[$user{$client}{room}]{in}{$a}";
				}
			}
		else {
			if ($user{$a}{roomdesc}){
				$outbuffer{$client}.=", $user{$a}{roomdesc}"; 
				}
			else {
				$outbuffer{$client}.= ", $room[$user{$client}{room}]{in}{$a}";
				}
			}
		}
	
	}
if ($b){
	$outbuffer{$client}.="\r\n";
	
	}
local $b=0;
foreach $a (keys %{$room[$user{$client}{room}]{items}}){
	if (defined($item{$a}{noshow})){
		next;
		}
		unless($b==1){
			$b=1;
			if ($item{$a}{roomdesc}){
				$outbuffer{$client}.= "Lying here is : $item{$a}{roomdesc}";
				}
			else {
				$outbuffer{$client}.= "Lying here is : $item{$a}{name}";
				}
			}
		else {
			if ($item{$a}{roomdesc}){
				$outbuffer{$client}.=", $item{$a}{roomdesc}"; 
				}
			else {
				$outbuffer{$client}.= ", $item{$a}{name}";
				}
			}
	}
if ($b){
	$outbuffer{$client}.="\r\n";
	
	}
$outbuffer{$client}.= "Obvious exits: $room[$user{$client}{room}]{obvious}";


$outbuffer{$client}.= "\r\n$prompt";
}

sub move {
my $dest=shift;
my $message=shift;
my $message2=shift;
unless($client){
	my $client=shift;
	}
if(roundcheck()){
	return;
	}
#print "AAA\n";
if ($user{$client}{position} and $user{$client}{position} ne "stand"){
	$outbuffer{$client}.="You'll have to stand to do that\r\n$prompt";
	return;
	}
removefromroom($client);
$user{$client}{hiding}=undef;
say("$message",$user{$client}{room});
say("$message2",$dest);
addtoroom($dest,$client);
look();
}

sub removefromroom {
my $e=shift;
unless ($e){
	print "something very strange is going on\n";
	return;
	}
unless ($user{$e}){
	print "major error here\n";
	}
unless ($user{$e}{room}){
	print "bigger errror here\n";
	}
delete($room[$user{$e}{room}]{in}{$e});
}
sub addtoroom {
my $room=shift;
my $person=shift;
$user{$person}{room}=$room;
$room[$room]{in}{$client}=$user{$client}{name};
#print "moving $person to $room\n";
}
sub additemtoroom {
my $room=shift;
my $item=shift;
$room[$room]{items}{$item}=$item{$item}{name};
}
sub removeitemfromroom {
my $room=shift;
my $item=shift;
print "removing $item from $room\n";
delete $room[$room]{items}{$item};

return 1;
}	
sub makeitem {
my $item=shift;
unless ($itemtemplate{$item}){
	print "tried to create bad item $item\r\n";
	return 0;	
	}	
$itemtotal++;
$item{$itemtotal}=$itemtemplate{$item};
&savemuddata;
return $itemtotal;

}
sub delete {
$a=shift;
save($a);
say("$user{$a}{name} has left the universe.",$user{$a}{room});
removefromroom($a);
delete $inbuffer{$a};
delete $outbuffer{$a};
delete $ready{$a};
delete $user{$a};
delete $last{$a};		
delete $type{$a};
$select ->remove($a);
unless (close($a)){
	print "error $!\n";
	}
print "$a has been hung up on\n";
}


sub locateitemfloor {
my $room=shift;
my $item=shift;
my $skip=shift;
chomp ($item);
foreach $a (keys %{$room[$room]{items}}){
#	print "looking for $item in $a\r\n";
	if ($item{$a}{name}=~/$item/i){
		if ($skip){
		$skip--;	
			}
		else {
			return $a;
			}
		}
	}
return 0;		
}
sub locateitem{
$room=shift;
$item=shift;
if ($a=locateitemfloor($room,$item)){
	return $a;
	}
return 0;
}
sub monsterdecay {
$a=shift;
removefromroom($a);
#$node[$user{$a}{monster}{node}]{maxused}--;
#print "$user{$a}{node}";
${$user{$a}{node}}{maxused}--;
#print "${$user{$a}{node}}{maxused}\n";
delete $user{$a};
delete $outbuffer{$a};
delete $inbuffer{$a};
delete $ready{$a};
delete $type{$a};
if (defined($user{$a})){
	print "nope, it's not going boom\n";
	die;
	}
}
sub playerdecay {
$a=shift;
say2("$user{$a}{name} is magicaly reborn!", $user{$a}{room}, "The gods smile upon you and you are returned to life!", $a);
$type{$a}="normal";
$user{$a}{vitality}=$user{$a}{vitalitymax};
$user{$a}{roomdesc}="$user{$a}{name} is lying around";
$node{$user{$a}{node}}{maxused}--;
delete $user{$a}{dead};
}
sub descend {
	my $str=shift;
	my $key=shift;
	if (ref($str) eq "HASH"){
		#is a refrence need to descend
		$string.="<$key>\n";
		foreach $a (keys %{$str}){
			descend(${$str}{$a},$a);
			}
		$string.="</$key>\n";
		}
	elsif (ref($str) eq "ARRAY"){
		return;
		}
	else {
		#is a plain value, save it.
		$string.="<$key=$str>\n";
		}
	}
sub save {
if (&saveplayer){
	$outbuffer{$client}.="You have been saved\r\n$prompt";
	}
else {	
	$outbuffer{$client}.="You have NOT been saved, something went wrong\r\n";
	}	
}
sub saveplayer {
my $client=(shift or $client);
local $string;
foreach $a (keys %{$user{$client}}){
	descend($user{$client}{$a},$a);
	}
unless (open (PLAYER, ">players/$user{$client}{name}")){
	$outbuffer{$client}.="$!";
	return 0;
	}
print PLAYER $string;
close PLAYER;
foreach $a (%{$user{$client}{health}}){
	foreach $b (%{$user{$client}{health}{$a}{wear}}) {
		if ($user{$client}{health}{$a}{wear}{$b}){
			print "wearing save, $a $b\n";
			&saverealitem($user{$client}{health}{$a}{wear}{$b});
			}
		}
	if ($user{$client}{health}{$a}{hold}){
		print "holding save $user{$client}{health}{$a}{hold}\n";
		&saverealitem($user{$client}{health}{$a}{hold});	
		}
		
	}
return 1;
}

return 1;