/**
 *  殺しの７並べ
 *  copyright  M.Shiojima
 *  2009-05-28 ver. 1.00
 */
var isTestEnable = false;

var TIMEOUT = 800;

function loadMsgFinish(message) {
    app.makeAiHash(message);
    var subwin = document.getElementById("subwin");
    subwin.style.display = "none";
    app.setup();
    app.startGame();
}

function Koroshi() {
    this.aiSelectList = new Array("(人間)", "単細胞", "冷静", "殺し屋", "臆病者", "凶暴");

    if (isIE()) {
    	this.spades = 'spades.gif';
    	this.hearts = 'hearts.gif';
    	this.diams = 'diams.gif';
    	this.clubs = 'clubs.gif';
    } else {
    	this.spades = 'spades.png';
    	this.hearts = 'hearts.png';
    	this.diams = 'diams.png';
    	this.clubs = 'clubs.png';
    }
    this.markList = new Array('', this.spades, this.hearts,
            this.diams, this.clubs);
    this.numberList = new Array('', 'A', '2', '3', '4', '5', '6', '7',
                    '8', '9', '10', 'J', 'Q', 'K');
    this.startPosList = new Array('', new Position(60, 240), new Position(180,480), new Position(300, 240), new Position(180, 0) );

    this.pause = false;
    this.playtimer = null;
    this.selectedkey = null;
    this.selectedtkey = null;
    this.animetimes = 10;
    this.message = new Message();

    this.setup = function() {
        this.aiList = new Array('',
            this.assignPlayer(0, 1),
            this.assignPlayer(2, 2),
            this.assignPlayer(3, 3),
            this.assignPlayer(4, 4)
        );

        this.totalWinList = new Array(0, 0, 0, 0, 0);

        this.playerCount = 4;
        this.option = new Options();
        if (isIPhone()) {
        	this.animetimes = 0;
        }
    }

    this.init = function() {
        this.nextPlayer = 1;
        this.agariCount = 0;
        for (var ix = 1; ix <= this.playerCount; ix++) {
            var ai = this.aiList[ix];
            ai.init();
        }
        this.onboadHash = new Object();
        this.killedHash = new Object();
        this.msgList = new Array();
        this.restMsgList = new Array();

        var allCardList = makeAllCardList();
        this.dispMsgAll();
        this.divideCard(allCardList);
        this.dispTefuda();
        this.dispBafuda();
        this.dispInfo();
        if (this.option.sevensPlaced) {
            this.place7s();
        } else {
            this.placeHeart7();
        }
        this.pause = false;
        if (isIPhone()) {
        	hideAddrBar();
        }
        this.play();
    }

    // 一手番分のプレイを行なう
    this.play = function() {
        this.isDoneKill = false;
        if (this.pause) {
            this.playtimer = window.setTimeout("app.play()", TIMEOUT);
            return;
        }

        if (animeCtrl.objList.length > 0) {
            this.playtimer = window.setTimeout("app.play()", TIMEOUT);
            return;
        }

        var player = this.aiList[this.nextPlayer];
        if ( (player.agari > 0) && (this.agariCount < this.playerCount) ) {
            this.progressNext();
            this.playtimer = window.setTimeout("app.play()", 0);
            return;
        }
        this.dispTefuda();
        this.dispBafuda();
        this.dispInfo();
        if (this.dispMsg() ) {
            this.playtimer = window.setTimeout("app.play()", TIMEOUT);
            return;
        }
        if ( (player.agari == 0) && (this.isAgari(this.nextPlayer) ) ) {
                this.agariCount++;
                player.agari = this.agariCount;
                player.printAgariMsg();
        }
        if (this.agariCount >= this.playerCount) {
            this.gameFinish();
            this.playtimer = null;
            return;
        }
        if (player.agari > 0) {
            this.progressNext();
            this.playtimer = window.setTimeout("app.play()", 0);
            return;
        }
        if (this.isAgari(this.nextPlayer) ) {
                this.agariCount++;
                player.agari = this.agariCount;
                player.printAgariMsg();
        }

        if (this.playerCardList[this.nextPlayer].length > 0) {
            var list = makePlaceableList(
                    this.playerCardList[this.nextPlayer], this.onboadHash);
            if (list.length == 0) {
                player.printPassMsg();
                player.passCount++;
            } else {
                if (player.isUser) {
                    this.printMsg(0, player.fullName + "の番です");
                    this.dispMsg();
                    if (this.userCount > 1) {
                        alertMsg(player.fullName + "の番です");
                    } else {
                        window.setTimeout("app.clearMsg()", TIMEOUT);
                    }
                    this.playtimer = null;
                    return;
                }
                player.playOnce();
            }
        }
        if (this.isAgari(this.nextPlayer) ) {
            this.agariCount++;
            player.agari = this.agariCount;
            player.printAgariMsg();
        }
        if (! this.isDoneKill || (this.option.doubleImpulse == 0)) {
            this.progressNext();
        } else {
            this.printMsg(0, player.fullName + "が続けてプレイします。");
        }
        this.playtimer = window.setTimeout("app.play()", TIMEOUT);
    }

    // メッセージ読み込み処理
    this.loadMsg = function() {
        if (window.widget) {
            widget.onshow = onshow;
            widget.onhide = onhide;
        }
        this.infoIcon
            = new OpacityIcon(document.getElementById("ibutton"), "app.infoIcon");
        var subwin = document.getElementById("subwin");
        subwin.style.left = "170";
        subwin.style.top = "120";
        var html = '<table><tr><td style="text-align: center;">';
        html += '<img src="' + this.spades + '">';
        html += "読み込み中です。";
        html += '<img src="' + this.hearts + '">';
        html += "<br>";
        html += '<img src="' + this.diams + '">';
        html += "しばらくお待ちください";
        html += '<img src="' + this.clubs + '">';
        html += "</td><tr></table>";
        subwin.innerHTML = html;
        subwin.style.display = "block";
        loadMsgFinish(this.message);
    }

    // ゲーム開始処理
    this.startGame = function() {
        this.loadSetting();
        var subwin = document.getElementById("subwin");
        subwin.style.left = "110";
        subwin.style.top = "85";
        var html = "<form name='form0'>";
        html += "<table><tr><td class='subwinBody'>";
        html += "ゲームを開始します。<br/><br/>";
        if (isIPhone()) {
            html += "<font style='font-size:14px;'>iPhone/iPod Touchでは<br/>横向きで遊んでください。<br/></font>";
            html += "<font style='font-size:12px;'>下のメニューの「＋」を押して「ホーム画面に追加」を選択すると、いつでもホーム画面からこのゲームを呼び出せます。</font>";
        }
        html += "<tr><td class='subwinFooter' nowrap='nowrap'>";
        html += "<a class='button' onclick='app.changePlayer()'";
        html += " >メンバー変更</a>&nbsp;&nbsp;";
        html += "<a class='button' onclick='app.selectOptions()'";
        html += " >オプション</a>&nbsp;&nbsp;";
        html += "<a class='button' onclick='app.dispUra()'>情報表示</a>";
        html += "</td></tr><tr><td colspan='2' align='center' >";
        html += "<a class='button' onclick='app.restart()'>ゲーム開始</a>";
        html += "</td></tr></table>";
        html += "</form>";
        subwin.innerHTML = html;
        subwin.style.display="inline";
	    var googlead = document.getElementById("googlead");
	    googlead.style.display="inline";
        if (isIPhone()) {
        	hideAddrBar();
        }
    }

    // ゲーム終了処理
    this.gameFinish = function() {
        this.dispTefuda();
        this.dispBafuda();
        this.dispInfo();
        this.dispMsg();
        var win = null;
        for (var i = 1; i <= this.playerCount; i++) {
            var player = this.aiList[i];
            if (win == null) {
                win = player;
            } else if (player.killedCount < win.killedCount) {
                minKilled = player.killedCount;
                win = player;
            } else if (player.killedCount == win.killedCount) {
                if (player.killCount > win.killCount) {
                    win = player;
                } else if (player.killCount == win.killCount) {
                    if (player.agari < win.agari) {
                        win = player;
                    }
                }
            }
        }

        this.totalWinList[win.id]++;
        var subwin = document.getElementById("subwin");
        var html = "";
        html += "<table><tr><td class='subwinBody'>";
        html += "ゲーム終了<br>"
        html += win.fullName + "の勝利です！"
        html += "<br>";
        html += "<br>";
        html += "<table style='display: inline;'>";
        for (i = 1; i <= this.playerCount; i++) {
            if (this.totalWinList[i] == 0) {
                continue;
            }
            html += "<tr>";
            html += "<td>" + this.aiList[i].name + "</td>";
            html += "<td>" + this.totalWinList[i] + "勝</td>";
            html += "</tr>";
        }
        html += "</table>";
        html += "</td></tr>";
        html += "<tr><td class='subwinFooter'>";
        html += "<a class='button' onclick='app.changePlayer()' ";
        html += ">メンバー変更</a>&nbsp;&nbsp;";
        html += "<a class='button' onclick='app.selectOptions()'";
        html += " >オプション</a>&nbsp;&nbsp;";
        html += "<a class='button' onclick='app.dispUra()'>情報表示</a>";
        html += "</td></tr><tr><td colspan='2' align='center'>";
        html += "<a class='button' onclick='app.restart()'>もう一度</a>";
        html += "</td></tr></table>";
        subwin.innerHTML = html;
        subwin.style.display="inline";
	    var googlead = document.getElementById("googlead");
	    googlead.style.display="inline";
        if (isIPhone()) {
        	hideAddrBar();
        }
    }

    // もう一度ゲームを行なう
    this.restart = function() {
        var subwin = document.getElementById("subwin");
        subwin.style.display = "none";
        var googlead = document.getElementById("googlead");
        googlead.style.display="none";
        this.init();
    }

    // プレイヤーの手札を表示する。
    this.dispTefuda = function() {
        var elm = document.getElementById("tefuda");
        var html = ""

        html += "<table><tr>";

        var isPlayerTurn = (this.aiList[this.nextPlayer].isUser);
        for (var i = 0; i < this.playerCardList[this.nextPlayer].length; i++) {
            var key = this.playerCardList[this.nextPlayer][i];
            var tefudaKey = "t-" + i;
            var ary = key.split(/-/);
            var mark = parseInt(ary[0], 10);
            var number = parseInt(ary[1], 10);
            html += "<td class='card'>";
            if (isPlayerTurn) {
                html += this.dispCard(mark, number, isPlayerTurn, tefudaKey);
            }
            html += "</td>";
        }

        html += "</tr></table>";
        elm.innerHTML = html;
    }

    // 一枚分のカードを表示する。
    this.dispCard = function(mark, no, eventEnable, tkey) {
        var key = makeKey(mark, no);
        var html = "";
        var classStr = "card";
        if (this.killedHash[key] ) {
            classStr="killedCard";
        }
        html += '<a class="' + classStr + '" id="' + tkey + '" ';
        if (eventEnable) {
        	if (! isIPhone()) {
	            html += 'onmouseover="app.onmouseover(\'' + key + '\', \''
	                    + tkey + '\')" ';
	            html += 'onmouseout="app.onmouseout(\'' + key + '\', \''
	                    + tkey + '\')" ';
        	}
            html += 'onclick="app.onclick(\'' + key + '\', \''
                    + tkey + '\')" ';
        }
        html += ">";
        html += '<img src="' + this.markList[mark];
        html += '" style="padding-left: 4px;display: block;"">';
        html += this.numberList[no];
        html += '</a>';
        return html;
    }

    // 場札を表示する
    this.dispBafuda = function() {
    	if (animeCtrl) {
    		animeCtrl.clearObj();
    	}
        var elm = document.getElementById("boad");
        var html = ""
        html += "<table>";

        for (var mark = 1; mark <= 4; mark++) {
            html += "<tr>";
            for (var no = 1; no <= 13; no++) {
                var key = makeKey(mark, no);
                html += "<td class='card'>";
                if (this.onboadHash[key]) {
                    html += this.dispCard(mark, no);
                } else {
                    html += "<div class='card' id='" + key + "'>&nbsp;</div>";
                }
                html += "</td>";
            }
            html += "</tr>";
        }

        html += "</table>";
        elm.innerHTML = html;
    }

    // 情報の表示
    this.dispInfo = function() {
        var elm = document.getElementById("info");
        var html = "";
        html += "<table>";
        html += "<tr class='infoHeader'>";
        html += "<th nowrap='nowrap'>名前</th><th nowrap='nowrap'>性格</th><th nowrap='nowrap'>残り枚数</th><th nowrap='nowrap'>殺された数</th>";
        html += "<th>殺した数</th>";
        html += "<th>パス回数</th><th>上がり順</th>";
        html += "</tr>";

        for (var i = 1; i <= this.playerCount; i++) {
            var player = this.aiList[i];
            html += "<tr class='info" + (i % 2) + "'>";
            html += "<td>" + player.name + "</td>";
            html += "<td>" + this.aiSelectList[player.aino] + "</td>";
            html += "<td>" + this.playerCardList[i].length + "</td>";
            html += "<td>" + player.killedCount + "</td>";
            html += "<td>" + player.killCount + "</td>";
            html += "<td>" + player.passCount + "</td>";
            html += "<td>" + player.agari + "</td>";
            html += "</tr>";
        }
        html += "</table>";
        elm.innerHTML = html;
    }

    // カードを配る
    this.divideCard = function(list) {
        this.playerCardList = new Object();
        this.killedCardList = new Object();
        var playerIx = 1;
        for (playerIx = 1; playerIx <= this.playerCount; playerIx++) {
            this.playerCardList[playerIx] = new Array();
            this.killedCardList[playerIx] = new Array();
        }
        playerIx = 1;

        for (var i = 0; i < list.length; i++) {
            var card = list[i];
            this.playerCardList[playerIx].push(card);
            playerIx = (playerIx >= this.playerCount) ? 1 : (playerIx + 1);
        }

        for (playerIx = 1; playerIx <= this.playerCount; playerIx++) {
            this.playerCardList[playerIx].sort();
        }
    }

    // ７の札を場に出す
    this.placeHeart7 = function() {
        for (var p = 1; p <= this.playerCount; p++) {
            var tefuda = this.playerCardList[p];
            for (var i = 0; i < tefuda.length; i++) {
                var key = tefuda[i];
                if (key == "3-07") {
                    this.placeOne(key, p);
                    this.nextPlayer = p;
                    this.progressNext();
                    return;
                }
            }
        }
    }

    // ７の札を場に出す
    this.place7s = function() {
        for (var p = 1; p <= this.playerCount; p++) {
            var tefuda = this.playerCardList[p];
            for (var i = 0; i < tefuda.length; i++) {
                var key = tefuda[i];
                var ary = key.split(/-/);
                if (parseInt(ary[1], 10) == 7) {
                    this.placeOne(key, p);
                }
            }
        }
    }

    // マウスが手札上に来た時のイベント処理
    this.onmouseover = function(key, tkey) {
    	this.dispcardplace(key, tkey);
    }
    
    // 手札上に対応する場所を表示する。
    this.dispcardplace = function(key, tkey) {
        var elm = document.getElementById(key);
        if (! elm) {
            return;
        }
        if (this.isPlaceEnable(key, this.onboadHash) ) {
            elm.style.border = "solid 2px #FFFF00";
        } else {
            elm.style.border = "solid 2px #FF0000";
        }
        elm.style.width = "30px";
        elm.style.height = "41px";
        elm = document.getElementById(tkey);
        elm.style.borderTop = "solid 2px #000000";
        elm.style.borderLeft = "solid 2px #000000";
        elm.style.borderRight = "none";
        elm.style.borderBottom = "none";
        elm.style.backgroundColor = "#AAAAAA";
    }
    	
    // マウスが手札上からはなれた時のイベント処理
    this.onmouseout = function(key, tkey) {
    	this.undispcardplace(key, tkey);
    }

    // 手札の位置の表示をやめる
    this.undispcardplace = function(key, tkey) {
	    var elm = document.getElementById(key);
	    if (! elm) {
	        return;
	    }
	    elm.style.border = "none";
	    elm.style.width = "34px";
	    elm.style.height = "45px";
	    elm = document.getElementById(tkey);
	    elm.style.borderRight = "solid 2px #000000";
	    elm.style.borderBottom = "solid 2px #000000";
	    elm.style.borderLeft = "none";
	    elm.style.borderTop = "none";
	    elm.style.backgroundColor = "#FFFFFF";
    }

    // カードをクリックした時のイベント処理
    this.onclick = function(key, tkey) {
    	if (isIPhone()) {
	    	if ( (this.selectedkey != null) && (this.selectedkey == key) ) {
	    		this.placecard(key, tkey);
	    	} else {
	    		if (this.selectedkey != null) {
	    			this.undispcardplace(this.selectedkey, this.selectedtkey);
	    		}
				this.selectedkey = key;
				this.selectedtkey = tkey;
				this.dispcardplace(key, tkey);
	    	}
    	} else {
    		this.placecard(key, tkey);
    	}
    }

    // カードを配置する
    this.placecard = function(key, tkey) {
        this.isDoneKill = false;
        if (! this.isPlaceEnable(key, this.onboadHash) ) {
            this.printMsg(0, "そのカードは置けませんよ");
            this.dispMsg();
            window.setTimeout("app.clearMsg()", TIMEOUT);
            return;
        }
        this.selectedkey = null;
        this.selectedtkey = null;
        this.placeOne(key, this.nextPlayer);
        if (this.isAgari(this.nextPlayer) ) {
            this.agariCount++;
            var player = this.aiList[this.nextPlayer];
            player.agari = this.agariCount;
            player.printAgariMsg();
        }
        if (!this.isDoneKill || (this.option.doubleImpulse == 0)) {
            this.progressNext();
        } else {
            this.printMsg(0, this.aiList[this.nextPlayer].fullName + "が続けてプレイします。");
        }
        this.play();
    }

    // 次のプレイヤーに手番を移す
    this.progressNext = function() {
        this.nextPlayer
            = (this.nextPlayer == this.playerCount) ? 1 : this.nextPlayer+1;
    }

    // 配置可能かどうかを判断する。
    this.isPlaceEnable = function(key, onboadHash) {
        var ary = key.split(/-/);
        var mark = parseInt(ary[0], 10);
        var no = parseInt(ary[1], 10);
        if (no == 7) {
            return true;
        }
        for (var vno = (no - 1); vno <= (no + 1); vno++) {
            if (vno < 1) {
                continue;
            }
            if (vno > 13) {
                continue;
            }
            for (var vmark = (mark - 1); vmark <= (mark + 1); vmark++) {
                if (vmark < 1) {
                    continue;
                }
                if (vmark > 4) {
                    continue;
                }
                if ( (vmark == mark) && (vno == no) ) {
                    continue;
                }
                var vkey = makeKey(vmark, vno);
                if (onboadHash[vkey]) {
                    return true;
                }
            }
        }

        return false;
    }

    // カードを配置する
    this.placeOne = function(key, p) {
        this.onboadHash[key] = p;
        this.playerCardList[p]
                = removeArray(this.playerCardList[p], key);
        var ary = key.split(/-/);
        var mark = parseInt(ary[0], 10);
        var no = parseInt(ary[1], 10);
        var cardkey = "a-" + key;
        var cobj = this.cardObj(cardkey);
        this.drawCard(cardkey, mark, no);
        animeCtrl.addObject(cobj, this.startPosList[p], getCardPosition(mark, no), this.animetimes);
        var ajustList = this.makeAjustList(mark, no);
        for (var i = 0; i < ajustList.length; i++) {
            var cKey = ajustList[i];
            if (! this.onboadHash[cKey]) {
                var killedHash = this.getKilledList(cKey, this.onboadHash);
                if (killedHash) {
                    for (var kk in killedHash) {
                        var kid = this.killCard(kk);
                        if (kid) {
                            this.aiList[this.nextPlayer].killCount++;
                            this.aiList[this.onboadHash[kk]].killedCount++;
                            this.aiList[this.nextPlayer].printKillMsg(kid);
                            this.aiList[kid].printKilledMsg(this.nextPlayer);
                        }
                        this.isDoneKill = true;
                    }
                }
            }
        }
    }

    this.cardObj = function(cardkey) {
        var cobj = document.getElementById(cardkey);
        if (! cobj) {
            cobj = document.createElement("div");
            cobj.id = cardkey;
            var pobj = document.getElementById("animecard");
            pobj.appendChild(cobj);
        }
        return cobj;
    }
    
    this.drawCard = function(cardkey, mark, no) {
        var cobj = document.getElementById(cardkey);
        cobj.style.display = "none";
        var html = "<table><tr><td class='card'>";
        html += this.dispCard(mark, no);
        html += "</td></tr></table>";
        cobj.innerHTML = html;
        cobj.style.position = "absolute";
    }

    // キーが有効かどうかを判定する。
    this.isKeyEnable = function(key) {
        var ary = key.split(/-/);
        var mark = parseInt(ary[0], 10);
        var no = parseInt(ary[1], 10);
        if (mark < 1) {
            return false;
        }
        if (mark > 4) {
            return false;
        }
        if (no < 1) {
            return false;
        }
        if (no > 13) {
            return false;
        }
        return true;
    }

    // 殺されたかどうかを判定する。
    this.getKilledList = function(key, onboadHash) {
        var ary = key.split(/-/);
        var mark = parseInt(ary[0], 10);
        var no = parseInt(ary[1], 10);
        if (! this.isKeyEnable(key) ) {
            return false;
        }
        var adjustHash = new Object();
        this.appendAdjustTefuda(key, onboadHash, adjustHash);
        var length = 0;
        var maxm = 0;
        var minm = 99;
        var maxn = 0;
        var minn = 99;
        for (var k in adjustHash) {
            length++;
            ary = k.split(/-/);
            mark = parseInt(ary[0], 10);
            no = parseInt(ary[1], 10);
            if (mark > maxm) {
                maxm = mark;
            }
            if (mark < minm) {
                minm = mark;
            }
            if (no > maxn) {
                maxn = no;
            }
            if (no < minn) {
                minn = no;
            }
        }
        if (length == 0) {
            return false;
        }
        if (this.option.maxKoroshi < length) {
            return false;
        }

        var mlength = maxm - minm + 1;
        var nlength = maxn - minn + 1;
        if (length != mlength * nlength) {
            return false;
        }
        if (! this.option.threeWall) {
            if (mlength == 4) {
                return false;
            }
        }

        return adjustHash;
    }

    // 隣を追加する
    this.appendAdjustTefuda = function(key, onboadHash, adjustHash) {
        if (! this.isKeyEnable(key) ) {
            return;
        }
        if (onboadHash[key] ) {
            return;
        }
        if (adjustHash[key] ) {
            return;
        }
        adjustHash[key] = true;
        var ary = key.split(/-/);
        var mark = parseInt(ary[0], 10);
        var no = parseInt(ary[1], 10);
        var ckeyList = this.makeAjustList(mark, no);
        for (var i = 0; i < ckeyList.length; i++) {
            var ckey = ckeyList[i];
            this.appendAdjustTefuda(ckey, onboadHash, adjustHash);
        }
    }

    // カードを殺す
    this.killCard = function(key) {
        for (var p = 1; p <= this.playerCount; p++) {
            for (var i = 0; i < this.playerCardList[p].length; i++) {
                if (this.playerCardList[p][i] == key) {
                    this.killedHash[key] = p;
                    this.placeOne(key, p);
                    return p;
                }
            }
        }
    }

    // 前後左右のキーを作成する
    this.makeAjustList = function(mark, no) {
        var ckeyList = new Array();
        ckeyList.push(makeKey(mark - 1, no) );
        ckeyList.push(makeKey(mark + 1, no) );
        ckeyList.push(makeKey(mark, no - 1) );
        ckeyList.push(makeKey(mark, no + 1) );
        return ckeyList;
    }

    // 上がりかどうかを判定する
    this.isAgari = function(userId) {
        var cardList = this.playerCardList[userId];
        if (cardList.length == 0) {
            return true;
        }
        return false;
    }

    // メッセージを表示する
    this.printMsg = function(id, msg) {
        var str = "";
        if (id) {
            str += this.aiList[id].name + "&gt;&nbsp;"
        }
        str += msg;
        if (! this.existMsgInList(str)) {
        	this.restMsgList.push(str);
        }
    }

    // メッセージを含んでいるかどうかをチェックする。
    this.existMsgInList = function(str) {
    	for (var ix = 0; ix < this.restMsgList.length; ix++) {
    		if (str == this.restMsgList[ix]) {
    			return true;
    		}
    	}
    	return false;
    }

    // メッセージが残っていたら、それを一つだけ追加する
    this.dispMsg = function() {
        var elm = document.getElementById("msgbox");
        if (this.restMsgList.length > 0) {
            var msg = this.restMsgList.shift();
            elm.innerHTML = "<table><tr><td>" + msg + "</td></tr></table>";
            elm.style.display = "inline";
            this.msgList.push(msg);
            this.dispMsgAll();
            return true;
        }
        elm.style.display = "none";
        return false;
    }

    // メッセージを表示する。
    this.dispMsgAll = function() {
        var elm = document.getElementById('message');
        if (elm) {
            var html = "";
            html += "<table>";
            for (var i = 0; i < 100; i++) {
                var ix = this.msgList.length - 1 - i;
                if (ix < 0) {
                    break;
                }
                html += "<tr><td>";
                html += this.msgList[ix];
                html += "</td></tr>";
            }
            html += "</table>";
            elm.innerHTML = html;
        }
    }

    this.clearMsg = function() {
        var elm = document.getElementById("msgbox");
        elm.style.display = "none";
    }

    this.changePlayer = function() {
        var subwin = document.getElementById("subwin");
        subwin.style.display="inline";
        var html = "<form name='form0'>";
        html += "<table><tr><td class='subwinBody'>";
        html += "<table>";
        for (var i = 1; i <= this.playerCount; i++) {
            var player = this.aiList[i];
            var pname = player.name;
            var ai = this.aiSelectList[player.id];
            html += "<tr>";
            html += "<td><input name='name" + i + "' value='" + pname + "'></td>";
            html += "<td><select name='ai" + i + "' onchange='app.changeName(" + i + ")'>";
            for (var j = 0; j < this.aiSelectList.length; j++) {
                html += "<option value='" + j + "' ";
                html += ((j == player.aino) ? "selected='selected'" : "") + ">";
                html += this.aiSelectList[j] + "</option>";
            }
            html += "</select>";
            html += "</td>";
            html += "</tr>";
        }
        html += "</table>";
        html += "<tr><td class='subwinFooter'>";
        html += "<a class='button' onclick='app.commitPlayer()'>決定</a>";
        html += "</td></tr></table>";
        html += "</form>";
        subwin.innerHTML = html;
    }
    
    // プレイヤー名を変更する
    this.changeName = function(i) {
    	var selix = document.forms['form0']['ai' + i].selectedIndex;
    	document.forms['form0']['name' + i].value = this.aiHash[selix].name;
    }

    // プレイヤー変更を確定する
    this.commitPlayer = function() {
        for (var i = 1; i <= this.playerCount; i++) {
            var name = document.forms.form0['name' + i].value;
            var aino = parseInt(document.forms.form0['ai' + i].value);
            this.aiList[i] = this.assignPlayer(aino, i, name);
        }
        this.saveSetting();
        this.startGame();
    }

    // 全カードを作成する
    function makeAllCardList() {
        var allList = new Array();
        for (var mark = 1; mark <= 4; mark++) {
            for (var no = 1; no <= 13; no++) {
                var key = makeKey(mark, no);
                allList.push(key);
            }
        }

        return randomArray(allList);
    }

    this.selectOptions = function() {
        var subwin = document.getElementById("subwin");
        subwin.style.display="inline";
        var html = "<form name='form0'>";
        html += "<table><tr><td class='subwinBody'>";
        html += "<table>";
        html += "<tr><td colspan='2'><h4>オプション</h4></td></tr>";
        html += "<tr>";
        html += "<td>殺し成立の最大枚数</td>";
        html += "<td>";
        html += "<select name='maxKoroshi'>";
        for (var ix = 0; ix < this.option.maxKoroshiList.length; ix++) {
            var v = this.option.maxKoroshiList[ix];
            html += "<option value='" + v + "' ";
            if (v == this.option.maxKoroshi) {
                html += "selected='true' ";
            }
            html += ">" + v + "</option>";
        }
        html += "</select>";
        html += "</td>";
        html += "</tr>";
        html += "<tr>";
        html += "<td>３方向壁で殺し成立</td>";
        html += "<td><input type='checkbox' name='threeWall'";
        if (this.option.threeWall == 1) {
            html += " checked='true'";
        }
        html += "/></td>";
        html += "</tr>";
        html += "<tr>";
        html += "<td>最初に７札を並べておくか</td>";
        html += "<td><input type='checkbox' name='sevensPlaced'";
        if (this.option.sevensPlaced == 1) {
            html += " checked='true'";
        }
        html += "/></td>";
        html += "</tr>";
        html += "<tr>";
        html += "<td>殺したらもう一度手番を行なう</td>";
        html += "<td><input type='checkbox' name='doubleImpulse'";
        if (this.option.doubleImpulse == 1) {
            html += " checked='true'";
        }
        html += "/></td>";
        html += "</tr>";
        html += "</table>";
        html += "</td></tr>";
        html += "<tr><td class='subwinFooter'>";
        html += "<a class='button' onclick='app.commitOptions()'>決定</a>";
        html += "</td></tr></table>";
        html += "</form>";
        subwin.innerHTML = html;
    }

    this.commitOptions = function() {
        this.option.maxKoroshi = parseInt(document.forms.form0["maxKoroshi"].value);
        this.option.threeWall = document.forms.form0["threeWall"].checked ? 1 : 0;
        this.option.sevensPlaced = document.forms.form0["sevensPlaced"].checked ? 1 : 0;
        this.option.doubleImpulse = document.forms.form0["doubleImpulse"].checked ? 1 : 0;
        this.saveSetting();
        this.startGame();
    }

    this.saveSetting = function() {
        saveValue("koroshiCountOfPlayers", this.aiList.length - 1);
        for (var pno = 1; pno < this.aiList.length; pno++) {
            var key = "koroshiP" + pno;
            saveValue(key + "name", this.aiList[pno].name);
            saveValue(key + "aino", this.aiList[pno].aino);
        }
        saveValue("koroshiMaxKoroshi", this.option.maxKoroshi);
        saveValue("koroshiThreeWall", this.option.threeWall);
        saveValue("koroshiSevensPlaced", this.option.sevensPlaced);
        saveValue("koroshiDoubleImpulse", this.option.doubleImpulse);
    }

    this.loadSetting = function() {
        var value = loadValue("koroshiCountOfPlayers");
        if ( (! value) || (isNaN(value)) ) {
            return false;
        }
        this.playerCount = parseInt(value);
        if (this.playerCount != 4) {
            return false;
        }

        this.aiList = new Array();
        this.aiList.push("");
        this.userCount = 0;
        for (var pno = 1; pno <= this.playerCount; pno++) {
            var key = "koroshiP" + pno;
            var name = loadValue(key + "name");
            if (! name) {
                name = "";
            }
            var aino = loadValue(key + "aino");
            if ((! aino) || isNaN(aino)) {
                aino = 0;
            }
            aino = parseInt(aino);
            var ai = this.assignPlayer(aino, pno, name);
            if (ai.isUser) {
                this.userCount++;
            }
            this.aiList.push(ai);
        }
        value = loadValue("koroshiMaxKoroshi");
        if ( (! value) || (isNaN(value) ) ) {
            value = 1;
        }
        this.option.maxKoroshi = parseInt(value);

        value = loadValue("koroshiThreeWall");
        if ( (! value) || (isNaN(value) ) ) {
            value = 0;
        }
        this.option.threeWall = parseInt(value);

        value = loadValue("koroshiSevensPlaced");
        if ( (! value) || (isNaN(value) ) ) {
            value = 0;
        }
        this.option.sevensPlaced = parseInt(value);

        value = loadValue("koroshiDoubleImpulse");
        if ( (! value) || (isNaN(value) ) ) {
            value = 0;
        }
        this.option.doubleImpulse = parseInt(value);

        return true;
    }

    this.makeAiHash = function(message) {
        try {
            this.aiHash = new Object();
            var aiList = message.aiList;
            for (var ix = 0; ix < aiList.length; ix++) {
                var ai = aiList[ix];
                var aino = ai.aino;
                var msgHash = ai.msgHash;
                var ainame = ai.defaultName;
                this.aiHash[aino] = createPlayer(aino, 0, ainame, msgHash);
            }
        } catch (e) {
            alertMsg("メッセージの読み込みエラー");
        }
    }

    this.assignPlayer = function(type, no, name) {
        var ai = clone(this.aiHash[type]);
        ai.id = no;
        if (name) {
            ai.name = name;
        }
        ai.fullName = getFullName(ai.name);
        ai.analyzerAi = new AnalyzerAi(ai);
        return ai;
    }

}

// スーツとランクからキーを作る
function makeKey(mark, no) {
    var nostr = (parseInt(no, 10) + 100) + "";
    return mark + "-" + nostr.substring(1);
}

// オプション管理クラス
function Options() {
    this.maxKoroshi = 9;
    this.threeWall = 0;
    this.sevensPlaced = 0;
    this.doubleImpulse = 0;

    this.maxKoroshiList = new Array(1, 2, 4, 6, 9, 12);
}

// カードの表示位置を算出する。
function getCardPosition(mark, no) {
    var top = mark * 49 + 32;
    var left = no * 36 - 12;

    var pos = new Position(top, left);
    return pos;
}

function alertMsg(msg) {
    var subwin = document.getElementById("subwin");
    subwin.style.textAlign = "center";
    var html = "<br>&nbsp;&nbsp;" + msg + "&nbsp;&nbsp;<br><br>";
    html += "<a class='button' onclick='eraseMsg()'> OK</a><br><br>";
    subwin.innerHTML = html;
    subwin.style.display = "block";
    subwin.style.left = "175";
    subwin.style.top = "130";
}

function eraseMsg() {
    var subwin = document.getElementById("subwin");
    subwin.style.display = "none";
    app.clearMsg();
}

function hideAddrBar() {
	setTimeout('scrollTo(10,5)', 100);
}

app = new Koroshi();
