#pragma save_binary


// skill.c
// From ES2
// Modified by Xiang for XKX (12/15/95)

#include <ansi.h>
#include <dbase.h>
#include <attribute.h>

mapping skills;
mapping learned;
mapping skill_map;
mapping skill_prepare;

mapping query_skills() { return skills; }
mapping query_learned() { return learned; }

void set_skill(string skill, int val)
{
	string *path,*fpath;

        if( !find_object(SKILL_D(skill))
        &&      file_size(SKILL_D(skill)+".c") < 0 )
                error("F_SKILL: No such skill (" + skill + ")\n");

        if( !mapp(skills) ) skills = ([ skill: val ]);
        else skills[skill] = val;
	
	if(!userp(this_object())||wizardp(this_object())) return ;
	//更改自己的技能或者巫师给巫师自己更改技能忽略
	path=explode(base_name(previous_object(0)), "/");
	fpath=({"adm","daemon","std","obj","feature","cmds"});
	if(member_array(path[0],fpath)==-1){ 
 	  	        log_file("static/set_skill",
			sprintf("%s非法更改了%s的技能(%s),数据为%d时间发生于: %s\n",
				base_name(previous_object(0)),this_object()->query("id"),skill,val,ctime(time()) ) );
	}
	//   log_file("set_skill",base_name(previous_object(1))+"非法调用了set_skill,更改了"
	//                        +this_object()->query("id")+"的技能("+skill+"),时间是"+ctime(time()));

}

int delete_skill(string skill)
{
        if( mapp(skills) ) {
                map_delete(skills, skill);
                if( mapp(learned) ) {
                        map_delete(learned, skill);
                        return undefinedp(learned[skill]);
                }
                return undefinedp(skills[skill]);
        }
        return 0;
}

// This function 'map' a skill <skill> to another skill <mapped_to>.
// If 2nd argument not given, cancel the mapped skill <skill>.
varargs void map_skill(string skill, string mapped_to)
{
        if( !mapped_to && mapp(skill_map) ) {
                map_delete(skill_map, skill);
                return;
        }

        if( !find_object(SKILL_D(skill))
        &&      file_size(SKILL_D(skill)+".c") < 0 )
                error("F_SKILL: No such skill (" + skill + ")\n");

        if( !mapp(skills) || undefinedp(skills[mapped_to]) )
                return;
                
        if( !mapp(skill_map) ) skill_map = ([ skill: mapped_to ]);
        else skill_map[skill] = mapped_to;
}

// This function 'prepare' a skill <skill> to another skill <mapped_to>.
// If 2nd argument not given, cancel the prepared skill <skill>.
varargs void prepare_skill(string skill, string mapped_to)
{
        if( !mapped_to && mapp(skill_prepare) ) {
                map_delete(skill_prepare, skill);
                return;
        }

        if( !find_object(SKILL_D(skill))
        &&      file_size(SKILL_D(skill)+".c") < 0 )
                error("F_SKILL: No such skill (" + skill + ")\n");

        if( !mapp(skills) || undefinedp(skills[mapped_to]) )
                return;
                
        if( !mapp(skill_prepare) ) skill_prepare = ([ skill: mapped_to ]);
        else skill_prepare[skill] = mapped_to;
}

string query_skill_mapped(string skill)
{
        if( mapp(skill_map) && !undefinedp(skill_map[skill]) )
                return skill_map[skill];
        return 0;
}

string query_skill_prepared(string skill)
{
        if( mapp(skill_prepare) && !undefinedp(skill_prepare[skill]) )
                return skill_prepare[skill];
        return 0;
}

varargs int query_skill(string skill, int raw)
{
        if( !raw ) {
                int s;
                
                s = query_temp("apply/" + skill);
                if( mapp(skills) ) {
                        s += skills[skill] / 2;
                        if( mapp(skill_map) )
                                s += skills[skill_map[skill]];
                }
                return s;
        }
        if( mapp(skills) && !undefinedp(skills[skill]) ) return skills[skill];
        return 0;
}

mapping query_skill_map()
{
        return skill_map;
}

mapping query_skill_prepare()
{
        return skill_prepare;
}

int skill_death_penalty()
{
        string *sk;
        int i;

        if( wizardp(this_object()) || !mapp(skills) ) return 0;

        sk = keys(skills);
        if( !mapp(learned) )
                for(i = 0; i<sizeof(sk); i++) {
                        skills[sk[i]]--;
                        if( skills[sk[i]]<0 ) map_delete(skills, sk[i]);
                }
        else
                for(i = 0; i<sizeof(sk); i++) {
                        if( (int)learned[sk[i]] > (skills[sk[i]]+1) * (skills[sk[i]]+1) / 2 )
                                map_delete(learned, sk[i]);
                        else {
                                skills[sk[i]]--;
                                if( skills[sk[i]]<0 ) map_delete(skills, sk[i]);
                        }
                }
        skill_map = 0;
        return 1;
}

varargs void improve_skill(string skill, int amount, int weak_mode)
{
        int spi;

//        if (!userp(this_object()))
//                return;
        if( !find_object(SKILL_D(skill))
        &&      file_size(SKILL_D(skill)+".c") < 0 )
                error("F_SKILL: No such skill (" + skill + ")\n");

        if( !weak_mode || !userp(this_object()) ) {
                if( !mapp(skills) ) skills = ([]);
                if( undefinedp(skills[skill]) ) skills[skill] = 0;
        }

        // Give learning penalty to those learning too much skills.
    spi = query_spi();
        if( sizeof(learned) > spi )
                amount /= sizeof(learned) - spi;

        if( !amount ) amount = 1;

        if( !mapp(learned) ) learned = ([ skill : amount ]);
        else (int)learned[skill] += amount;

        if( weak_mode==0 &&
//        userp(this_object()) && 
                learned[skill] > (skills[skill] + 1) * (skills[skill] + 1) ) {
                        skills[skill]++;
                        learned[skill] = 0;
                        if(userp(this_object()))
                        tell_object(this_object(), HIC "你的「" + to_chinese(skill) + "」进步了！\n" NOR);
                        SKILL_D(skill)->skill_improved(this_object());
    }else if( weak_mode==1 && 
//    userp(this_object())&&  
                (learned[skill]-amount) > (skills[skill] + 1) * (skills[skill] + 1) ) {
                        learned[skill] -= amount ;
            if(userp(this_object()))
            tell_object(this_object(), YEL "你的「" + to_chinese(skill) + "」无法再进步了！\n" NOR);
    }else if( weak_mode==2 && 
//    userp(this_object())&& 
                learned[skill] > (skills[skill] + 1) * (skills[skill] + 1)*2 ) {
                        skills[skill]++;
                        learned[skill] = 0;
                        if(userp(this_object()))
                        tell_object(this_object(), HIC "你的「" + to_chinese(skill) + "」进步了！\n" NOR);
                        SKILL_D(skill)->skill_improved(this_object());
        }
}

