// Aiを作成する
function createPlayer(type, id, name, msgHash) {
    var result = null;
    if (type == 0) {
        result = new UserPlayer(id, name);
    } else if (type == 1) {
        result = new SimpleAi(id, name);
    } else if (type == 2) {
        result = new InteligenceAi(id, name);
    } else if (type == 3) {
        result = new KillerAi(id, name);
    } else if (type == 4) {
        result = new OkubyouAi(id, name);
    } else if (type == 5) {
        result = new KyoubouAi(id, name);
    }
    result.msgHash = msgHash;
    return result;
}

// AI／ユーザー共通初期化処理
function initCommonPlayer(obj, id, name) {
    obj.name = (name) ? name : "あなた";
    obj.id = id;
    obj.isUser = false;
    obj.fullName = getFullName(obj.name);

    obj.playOnce = function() {
    }
    obj.printKillMsg = function(kid) {
    }
    obj.printKilledMsg = function(kid) {
    }
    obj.printAgariMsg = function() {
    }
    obj.printPassMsg = function() {
    }

    obj.init = function() {
        this.killedCount = 0;
        this.killCount = 0;
        this.passCount = 0;
        this.agari = 0;
    }
    obj.init();


}

function getFullName(name) {
    if (name == "あなた") {
        return name;
    }
    return name + "さん";
}

// ユーザープレイヤー
function UserPlayer(id, name) {
    this.aino = 0;
    initCommonPlayer(this, id, name);
    this.isUser = true;
    this.printKillMsg = function(kid) {
        if (kid == this.id) {
            app.printMsg(id, getMsg("selfKill", this, app.aiList[kid]));
        } else {
            app.printMsg(id, getMsg("kill", this, app.aiList[kid]));
        }
    }
    this.printKilledMsg = function(kid) {
        if (kid != this.id) {
            app.printMsg(id, getMsg("killed", this, app.aiList[kid]));
        }
    }
    this.printAgariMsg = function() {
        app.printMsg(id, getMsg("agari", this, null));
    }
    this.printPassMsg = function() {
        app.printMsg(id, getMsg("pass", this, null));
    }
}

// 一番単純なAI
function SimpleAi(id, name) {
    this.aino = 1;
    initCommonPlayer(this, id, name);
    this.playOnce = function() {
        var list = makePlaceableList(app.playerCardList[this.id], app.onboadHash);
        var d = dropDice(list.length);
        app.placeOne(list[d], this.id);
    }

    this.printKillMsg = function(kid) {
        if (kid == this.id) {
            app.printMsg(this.id, getMsg("selfKill", this, app.aiList[kid]));
        } else {
            app.printMsg(this.id, getMsg("kill", this, app.aiList[kid]));
        }
    }
    this.printKilledMsg = function(kid) {
        if (kid != this.id) {
            app.printMsg(this.id, getMsg("killed", this, app.aiList[kid]));
        }
    }
    this.printAgariMsg = function() {
        app.printMsg(this.id, getMsg("agari", this, null));
    }
    this.printPassMsg = function() {
        app.printMsg(this.id, getMsg("pass", this, null));
    }
}

// Analyzerを使用するAIの共通処理
function AnalyzerAi(ai) {
    this.ai = ai;
    this.playOnce = function() {
        var list = makePlaceableList(app.playerCardList[this.id], app.onboadHash);
        list = randomArray(list);
        this.analyzer.makePhash(this.id);
        maxPoint = -999;
        maxKey = null;
        for (var i = 0; i < list.length; i++) {
            var nextOnboad = this.analyzer.cloneOnboad(app.onboadHash);
            nextOnboad[list[i]] = this.id;
            this.analyzer.analyze(nextOnboad, this.id, list[i]);
            var p = this.countPoint();
            if (p > maxPoint) {
                maxPoint = p;
                maxKey = list[i];
            }
        }
        var nextOnboad = this.analyzer.cloneOnboad(app.onboadHash);
        nextOnboad[maxKey] = this.id;
        this.analyzer.analyze(nextOnboad, this.id, maxKey);
        this.placeMsg();
        app.placeOne(maxKey, this.id);
    }

    this.placeMsg = function() {
        if (this.analyzer.other4 >= 3) {
            app.printMsg(this.id, getMsg("kill3", this, null));
        } else if (this.analyzer.other4 == 2) {
            app.printMsg(this.id, getMsg("kill2", this, null));
        } else if (this.analyzer.other4 == 1) {
            app.printMsg(this.id, getMsg("kill1", this, null));
        } else if (this.analyzer.self4 > 0) {
            app.printMsg(this.id, getMsg("selfKill", this, null));
        }
    }
    this.printKilledMsg = function(kid) {
        if (kid != this.id) {
            app.printMsg(this.id, getMsg("killed", this, null));
        }
    }
    this.printAgariMsg = function() {
        app.printMsg(this.id, getMsg("agari", this, null));
    }
    this.printPassMsg = function() {
        app.printMsg(this.id, getMsg("pass", this, null));
    }
}

// 殺し屋AI
function KillerAi(id, name) {
    this.aino = 3;
    initCommonPlayer(this, id, name);
    this.countPoint = function() {
        var p = 0;
        p += this.analyzer.self1 * (-1);
        p += this.analyzer.self2 * (-2);
        p += this.analyzer.self3 * (-3);
        p += this.analyzer.self4 * (-10);
        p += this.analyzer.other1 * 1;
        p += this.analyzer.other2 * 2;
        p += this.analyzer.other3 * 3;
        p += this.analyzer.other4 * 10;
        return p;
    }
    this.analyzer = new Analyzer();
    this.analyzerAi = new AnalyzerAi(this);
    this.playOnce = this.analyzerAi.playOnce;
    this.placeMsg = this.analyzerAi.placeMsg;
    this.printKilledMsg = this.analyzerAi.printKilledMsg;
    this.printAgariMsg = this.analyzerAi.printAgariMsg;
    this.printPassMsg = this.analyzerAi.printPassMsg;
}

// 沈着冷静AI
function InteligenceAi(id, name) {
    this.aino = 2;
    initCommonPlayer(this, id, name);
    this.countPoint = function() {
        var p = 0;
        p += this.analyzer.self1 * (-3);
        p += this.analyzer.self2 * (-6);
        p += this.analyzer.self3 * (-9);
        p += this.analyzer.self4 * (-30);
        p += this.analyzer.other1 * 1;
        p += this.analyzer.other2 * 2;
        p += this.analyzer.other3 * 3;
        p += this.analyzer.other4 * 10;
        return p;
    }
    this.analyzer = new Analyzer();
    this.analyzerAi = new AnalyzerAi(this);
    this.playOnce = this.analyzerAi.playOnce;
    this.placeMsg = this.analyzerAi.placeMsg;
    this.printKilledMsg = this.analyzerAi.printKilledMsg;
    this.printAgariMsg = this.analyzerAi.printAgariMsg;
    this.printPassMsg = this.analyzerAi.printPassMsg;
}

// 臆病AI
function OkubyouAi(id, name) {
    this.aino = 4;
    initCommonPlayer(this, id, name);
    this.countPoint = function() {
        var p = 0;
        p += this.analyzer.self1 * (-10);
        p += this.analyzer.self2 * (-20);
        p += this.analyzer.self3 * (-30);
        p += this.analyzer.self4 * (-40);
        p += this.analyzer.other1 * 1;
        p += this.analyzer.other2 * 2;
        p += this.analyzer.other3 * 3;
        p += this.analyzer.other4 * 4;
        return p;
    }
    this.analyzer = new Analyzer();
    this.analyzerAi = new AnalyzerAi(this);
    this.playOnce = this.analyzerAi.playOnce;
    this.placeMsg = this.analyzerAi.placeMsg;
    this.printKilledMsg = this.analyzerAi.printKilledMsg;
    this.printAgariMsg = this.analyzerAi.printAgariMsg;
    this.printPassMsg = this.analyzerAi.printPassMsg;
}

// 凶暴AI
function KyoubouAi(id, name) {
    this.aino = 5;
    initCommonPlayer(this, id, name);
    this.countPoint = function() {
        var p = 0;
        p += this.analyzer.self1 * (-1);
        p += this.analyzer.self2 * (-2);
        p += this.analyzer.self3 * (-3);
        p += this.analyzer.self4 * (-50);
        p += this.analyzer.other1 * 10;
        p += this.analyzer.other2 * 20;
        p += this.analyzer.other3 * 30;
        p += this.analyzer.other4 * 100;
        return p;
    }
    this.analyzer = new Analyzer();
    this.analyzerAi = new AnalyzerAi(this);
    this.playOnce = this.analyzerAi.playOnce;
    this.placeMsg = this.analyzerAi.placeMsg;
    this.printKilledMsg = this.analyzerAi.printKilledMsg;
    this.printAgariMsg = this.analyzerAi.printAgariMsg;
    this.printPassMsg = this.analyzerAi.printPassMsg;
}

// 状況分析
function Analyzer() {
    this.cloneOnboad = function(onboad) {
        var result = new Object();
        for (var key in onboad) {
            result[key] = onboad[key];
        }

        return result;
    }

    // 手札のハッシュテーブルを作る
    this.makePhash = function(pid) {
        this.phash = new Object();
        for (var i = 0; i < app.playerCardList[pid].length; i++) {
            var key = app.playerCardList[pid][i];
            this.phash[key] = pid;
        }
    }

    // 手を分析する
    this.analyze = function(onboad, pid, pkey) {
        this.self0 = 0;
        this.self1 = 0;
        this.self2 = 0;
        this.self3 = 0;
        this.self4 = 0;
        this.other0 = 0;
        this.other1 = 0;
        this.other2 = 0;
        this.other3 = 0;
        this.other4 = 0;
        var ary = pkey.split(/-/)
        var mark = parseInt(ary[0]);
        var no = parseInt(ary[1]);
        var alist = app.makeAjustList(mark, no);
        var allKilled = new Object();
        for (var i = 0; i < alist.length; i++) {
            var k = alist[i];
            var killedList = app.getKilledList(k, onboad);
            if (killedList) {
                for (var kk in killedList) {
                    if (allKilled[kk]) {
                        continue;
                    }
                    if (this.phash[kk]) {
                        this['self4']++;
                    } else {
                        this['other4']++;
                    }
                    allKilled[kk] = true;
                }
            }
        }
        for (var mark = 1; mark <= 4; mark++) {
            for (var no = 1; no <= 13; no++) {
                var key = makeKey(mark, no);
                if (onboad[key]) {
                    continue;
                }
                if (allKilled[key]) {
                    continue;
                }
                var kabe = 0;
                var ckeyList = app.makeAjustList(mark, no);
                for (var i = 0; i < ckeyList.length; i++) {
                    var ckey = ckeyList[i];
                    if (! app.isKeyEnable(ckey) ) {
                        kabe++;
                    } else if (onboad[ckey]) {
                        kabe++;
                    }
                }
                if (this.phash[key]) {
                    this['self' + kabe]++;
                } else {
                    this['other' + kabe]++;
                }
            }
        }
    }
}

// 配置可能なカードのリストを作る
function makePlaceableList(tefudaList, onboadHash) {
    var result = new Array();
    for (var i = 0; i < tefudaList.length; i++) {
        var key = tefudaList[i];
        if (app.isPlaceEnable(key, onboadHash) ) {
            result.push(key);
        }
    }
    return result;
}

// メッセージを生成する
function getMsg(type, ai, other) {
    var msg = ai.msgHash[type];
    msg = msg.replace("@SFN@", ai.fullName);
    if (other) {
        msg = msg.replace("@TFN@", other.fullName);
    }
    return msg;
}
