/* This software is licensed under the BSD license. Copyright (c) 2011, Seussnu Koromotani All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the H.AltProject nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ var THIEF = { conf : { id : 'Thief', // was used "HTML's id", and "System tag". fontFace : 'monospace, sans-serif', textColor : '#FFFFFF', bgColor : '#000000', grayColor : '#7f7f7f', gridStyle : '0px none #888888', // css td border options mapWidth : 60, mapLength : 20, mapHeight : 256, language : null, languagePriolity : ['en', 'ja'], statusPosition : 'bottom', // top or bottom statusLineFormat : [ '${THIEF.global.adventurer.%get@name%} ♥:${THIEF.global.adventurer.%get@hp%} CT:${THIEF.global.adventurer.%get@ct%}', 'Turn : ${THIEF.global.turn}' ], messagePosition : 'top', // top or bottom messageLines : 3, messageHistorySize : 256, // infomationOverlap : true, mainWindowPosition : 'left', // css float option (left, right, none) msgOverflow : 'hidden', // css overflow option (visible, scroll, hidden, auto) itemSort : ['$', '"', ']', '[', '%', '!', '?', '+', '=', '/', '(', ')', '*' ], debugmode : false, debugMessageHeight : '10em' }, global : { actLV : null, turn : 0, keycode : NaN, hist : [], adventurer : null, // Player size : { Window : {width:Number.NaN, height:Number.NaN}, Main : {width:Number.NaN, height:Number.NaN}, // Input, Message, Map, Status Input : {width:Number.NaN, height:Number.NaN}, // 入力欄 Message : {width:Number.NaN, height:Number.NaN}, // メッセージ欄(入力上部) Map : {width:Number.NaN, height:Number.NaN}, // マップ Status : {width:Number.NaN, height:Number.NaN}, // ステータス Infomation : {width:Number.NaN, height:Number.NaN}, // 情報出力(インベントリの内容など) Debug : {width:Number.NaN, height:Number.NaN} // デバッグ情報 } }, KEY : { // 書かれていないキーは charCodeAt で充分だろう Backspace : 8, Enter : 13, Shift : 16, Ctrl : 17, Alt : 18, Esc : 27, Space : 32, PageUp : 33, // ! PageDown : 34, // " End : 35, // # Home : 36, // $ Left : 37, // % Up : 38, // & Right : 39, // ' Down : 40, // A : 'A'.charCodeAt(0), // A 65 B : 'B'.charCodeAt(0), C : 'C'.charCodeAt(0), D : 'D'.charCodeAt(0), E : 'E'.charCodeAt(0), F : 'F'.charCodeAt(0), G : 'G'.charCodeAt(0), H : 'H'.charCodeAt(0), I : 'I'.charCodeAt(0), J : 'J'.charCodeAt(0), K : 'K'.charCodeAt(0), L : 'L'.charCodeAt(0), M : 'M'.charCodeAt(0), N : 'N'.charCodeAt(0), O : 'O'.charCodeAt(0), P : 'P'.charCodeAt(0), Q : 'Q'.charCodeAt(0), R : 'R'.charCodeAt(0), S : 'S'.charCodeAt(0), T : 'T'.charCodeAt(0), U : 'U'.charCodeAt(0), V : 'V'.charCodeAt(0), W : 'W'.charCodeAt(0), X : 'X'.charCodeAt(0), Y : 'Y'.charCodeAt(0), Z : 'Z'.charCodeAt(0), // Z 90 a : 'a'.charCodeAt(0), // a 97 b : 'b'.charCodeAt(0), c : 'c'.charCodeAt(0), d : 'd'.charCodeAt(0), e : 'e'.charCodeAt(0), f : 'f'.charCodeAt(0), g : 'g'.charCodeAt(0), h : 'h'.charCodeAt(0), i : 'i'.charCodeAt(0), j : 'j'.charCodeAt(0), k : 'k'.charCodeAt(0), l : 'l'.charCodeAt(0), m : 'm'.charCodeAt(0), n : 'n'.charCodeAt(0), o : 'o'.charCodeAt(0), p : 'p'.charCodeAt(0), q : 'q'.charCodeAt(0), r : 'r'.charCodeAt(0), s : 's'.charCodeAt(0), t : 't'.charCodeAt(0), u : 'u'.charCodeAt(0), v : 'v'.charCodeAt(0), w : 'w'.charCodeAt(0), x : 'x'.charCodeAt(0), y : 'y'.charCodeAt(0), z : 'z'.charCodeAt(0), // z 122 // 91 = [ = WinKey // 92 = \ = WinKey F1 : 112, // p F2 : 113, // q F3 : 114, // r F4 : 115, // s F5 : 116, // t F6 : 117, // u F7 : 118, // v F8 : 119, // w F9 : 120, // x F10 : 121, // y F11 : 122, // z F12 : 123 // { = "Shift + [" }, E : { siz : 'siz', shapeWidth : 'shapeWidth', shapeHeight : 'shapeHeight', inventoryWidth : 'inventoryWidth', inventoryLength : 'inventoryLength', inventoryHeight : 'inventoryHeight', inventoryCellSize : 'inventoryCellSize', myOwner : 'myOwner', mergeable : 'mergeable', stackable : 'stackable', symbol : 'symbol', name : 'name', color : 'color', displayName : 'displayName', symbolName : 'symbolName', alphabet : 'alphabet', actObjectList : 'actObjectList', active : 'active', ct : 'ct', dex : 'dex', hp : 'hp', atk : 'atk' } }; // // Override // //noinspection JSUnusedGlobalSymbols window.onload = function(onload) { return function () { if (!!onload) { onload(); } THIEF.util.init(); }; }(window.onload); //noinspection JSUnusedGlobalSymbols window.onresize = function(onresize) { return function() { if (!!onresize) { onresize(); } if (window.innerWidth) { THIEF.global.size.Window.width = window.innerWidth; THIEF.global.size.Window.height = window.innerHeight; } else { THIEF.global.size.Window.width = document.documentElement.clientWidth || document.body.clientWidth || document.body.scrollWidth; THIEF.global.size.Window.height = document.documentElement.clientHeight || document.body.clientHeight || document.body.scrollHeight; } /* THIEF.global.size.Main.width = document.getElementById('Main').offsetWidth; THIEF.global.size.Main.height = document.getElementById('Main').offsetHeight; THIEF.global.size.Input = document.getElementById('Input').offsetWidth; THIEF.global.size.Input = document.getElementById('Input').offsetHeight; THIEF.global.size.Message = document.getElementById('Message').offsetWidth; THIEF.global.size.Message = document.getElementById('Message').offsetHeight; THIEF.global.size.Map = document.getElementById('Map').offsetWidth; THIEF.global.size.Map = document.getElementById('Map').offsetHeight; THIEF.global.size.Status = document.getElementById('Status').offsetWidth; THIEF.global.size.Status = document.getElementById('Status').offsetHeight; THIEF.global.size.Infomation = document.getElementById('Infomation').offsetWidth; THIEF.global.size.Infomation = document.getElementById('Infomation').offsetHeight; THIEF.global.size.Debug = document.getElementById('Debug').offsetWidth; THIEF.global.size.Debug = document.getElementById('Debug').offsetHeight; */ }; }(window.onresize); //noinspection JSUnusedGlobalSymbols document.onkeypress = function(onkeypress) { return function(event) { if (!!onkeypress) { onkeypress(event); } THIEF.global.keycode = THIEF.util.getKeyCode(event); THIEF.util.next(); }; }(document.onkeypress); if (!Object.create) { Object.create = function(o) { var func = function() { }; func.prototype = o; return new func(); }; } if (!Math.sign) { Math.sign = function(num) { if (num > 0) { return 1; } else { if (num < 0) { return -1; } else { return 0; } } }; } if (!Array.prototype.remove) { Array.prototype.remove = function(o) { var len = this.length; var result = false; for (var i = 0; i < len; i++) { if (!result && this[i] === o) { result = true; delete this[i]; } if (result) { // shifting this[i] = this[i + 1]; } } if (result) { this.length = len - 1; } return result; }; } if (!Array.prototype.getLast) { Array.prototype.getLast = function() { return this[this.length - 1]; }; } if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(elt /*, from*/) { var len = this.length; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) { from += len; } for (; from < len; from++) { if (from in this && this[from] === elt) { return from; } } return -1; }; } THIEF.command = {}; THIEF.command.goUp = function() { return this.move(0, -1); }; THIEF.command.goDown = function() { return this.move(0, 1); }; THIEF.command.goLeft = function() { return this.move(-1, 0); }; THIEF.command.goRight = function() { return this.move(1, 0); }; THIEF.command.goUpperLeft = function() { return this.move(-1, -1); }; THIEF.command.goUpperRight = function() { return this.move(1, -1); }; THIEF.command.goLowerLeft = function() { return this.move(-1, 1); }; THIEF.command.goLowerRight = function() { return this.move(1, 1); }; THIEF.command.refreshHTML = function() { THIEF.html.refresh(); return false; }; THIEF.command.rest = function() { return true; }; THIEF.command.pickup = function() { var objs = THIEF.global.actLV.getXyObjects(this.x, this.y); var finish = true; // メソッド書き換え if (objs.length > 2) { // 自分と床以外になにかあれば(?) var from = THIEF.global.actLV; var to = this; var exec = function(selected) { var result = false; for (var i = 0; i < selected.length; i++) { result = true; to.ct -= 20; // 重量オーバなら拾えない様にすること if (from.removeFromInventory(selected[i])) { to.addToInventory(selected[i]); THIEF.html.addMessage(selected[i].get(THIEF.E.displayName) + 'を拾った。'); } else { THIEF.html.addMessage(selected[i].get(THIEF.E.displayName) + 'は拾えない。'); } } //THIEF.util.updateStatus(); return result; }; this.action = THIEF.type.$.selecter(objs, exec, false, true); finish = false; } else { THIEF.html.addMessage('ホコリくらいしか落ちているものはない……'); } return finish; }; THIEF.command.drop = function() { // とりあえず一次元配列化 var list = []; if (typeof this.inventory !== 'undefined') { for (var x = 0; x < this.get(THIEF.E.inventoryWidth); x++) { if (typeof this.inventory[x] === 'undefined') { continue; } for (var y = 0; y < this.get(THIEF.E.inventoryLength); y++) { if (typeof this.inventory[x][y] === 'undefined') { continue; } var cell = this.inventory[x][y]; for (var i = 0; i < cell.length; i++) { //THIEF.html.addDebugMessage('[' + x + ', ' + y + '] ' + cell[i].get(THIEF.E.displayName) ); list.push(cell[i]); } } } } // メソッド書き換え if (list.length > 0) { var from = this; var to = THIEF.global.actLV; var exec = function(selected) { var act = false; if(selected.length > 0){ act = true; for (var i = 0; i < selected.length; i++) { from.ct -= 20; // 呪われてたら捨てれない様にすること if (from.removeFromInventory(selected[i])) { to.addToInventory(selected[i], from.x, from.y); THIEF.html.addMessage(selected[i].get(THIEF.E.displayName) + 'を置いた。'); } else { THIEF.html.addMessage(selected[i].get(THIEF.E.displayName) + 'は置けない。'); } } // キャラクターは再配置して、一番上にする。 var adx = THIEF.global.adventurer.x; var ady = THIEF.global.adventurer.y; to.removeFromInventory(THIEF.global.adventurer); to.addToInventory(THIEF.global.adventurer, adx, ady); //THIEF.util.updateStatus(); } return act; }; this.action = THIEF.type.$.selecter(list, exec, false, false); //result = this.action(); //result = false; } else { THIEF.html.addMessage('あなたは何も持っていない。'); } return false; }; THIEF.command.showInventory = function() { THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + 'のインベントリ表示を開始...'); var list = []; if (typeof this.inventory !== 'undefined') { for (var x = 0; x < this.get(THIEF.E.inventoryWidth); x++) { if (typeof this.inventory[x] === 'undefined') { continue; } for (var y = 0; y < this.get(THIEF.E.inventoryLength); y++) { if (typeof this.inventory[x][y] === 'undefined') { continue; } var cell = this.inventory[x][y]; for (var i = 0; i < cell.length; i++) { THIEF.html.addDebugMessage('[' + x + ', ' + y + '] ' + cell[i].get(THIEF.E.displayName)); list.push(cell[i]); } } } } if (list.length === 0) { THIEF.html.addMessage('インベントリは空です。'); } else { this.action = THIEF.type.$.selecter(list, this.action, true, false); } THIEF.html.addDebugMessage('...' + this.get(THIEF.E.displayName) + 'のインベントリ表示を完了。'); return false; }; THIEF.command.history = function() { var key = THIEF.KEY; var index = THIEF.global.hist.length; for (var i = THIEF.conf.messageLines - 1; i >= 0; i--) { var hoge = THIEF.global.hist.length - i; if (typeof THIEF.global.hist[hoge] !== 'undefined') { THIEF.html.addInfomation(THIEF.global.hist[hoge].turn + ' : ' + THIEF.global.hist[hoge].text); } } this.action = function() { var finish = false; switch (THIEF.global.keycode) { case key.Esc: finish = true; break; // Next case key.n: case key.j: case key.Enter: case key.Space: case key.PageDown: case key.Down: case '>'.charCodeAt(0): index--; if (index < 0) { index = THIEF.global.hist.length - 1; } break; // Prev case key.b: case key.k: case key.p: case key.PageUp: case key.Up: case '<'.charCodeAt(0): index++; if (index >= THIEF.global.hist.length) { index = 0; } break; default: break; } if (finish) { // 画面クリア THIEF.html.clearInfomation(''); // アクションを元に戻す this.action = THIEF.type.$.action; } else { THIEF.html.clearInfomation(); for (var i = THIEF.conf.messageLines - 1; i >= 0; i--) { if (typeof THIEF.global.hist[index - i] !== 'undefined') { THIEF.html.addInfomation(THIEF.global.hist[index - i].turn + ' : ' + THIEF.global.hist[index - i].text); } } } return false; }; return false; }; THIEF.command.extendedCommand = function() { var key = THIEF.KEY; THIEF.html.setInput('#'); var com = []; for (var name in THIEF.command) { com.push(name); } com.sort(); THIEF.html.addInfomation('-- COMMAND HINT --'); for (var i = 0; i < com.length; i++) { THIEF.html.addInfomation(com[i]); } var line = ''; var target = ''; this.action = function() { var finish = false; var update = false; if ((key.a <= THIEF.global.keycode && THIEF.global.keycode <= key.z) || (key.A <= THIEF.global.keycode && THIEF.global.keycode <= key.Z)) { line += String.fromCharCode(THIEF.global.keycode); update = true; } else if (THIEF.global.keycode === key.Space) { line += ' '; update = true; } else if (THIEF.global.keycode === key.Backspace) { line = line.slice(0, line.length - 1); update = true; } else if (THIEF.global.keycode === key.Esc) { THIEF.html.setInput(' '); THIEF.html.clearInfomation(); this.action = THIEF.type.$.action; } else if (THIEF.global.keycode === key.Enter) { THIEF.html.setInput(' '); THIEF.html.clearInfomation(); this.action = THIEF.type.$.action; if (typeof THIEF.command[target] === 'function') { finish = this[target](); } else { THIEF.html.addMessage(line + ' コマンドは存在しません。'); } } if (update) { THIEF.html.setInput('#' + line); var count = 0; for (var i = 0; i < com.length; i++) { if (com[i].indexOf(line, 0) === 0) { target = com[i]; count++; } } if (count === 1) { THIEF.html.addInput('' + target.slice(line.length, target.length) + ''); } else { THIEF.html.addInput('¦'); target = ''; } } return finish; }; return this.action(); }; THIEF.util = {}; THIEF.util.init = function() { // ブラウザ言語の取得 THIEF.conf.language = (THIEF.conf.language // || navigator.browserLanguage || navigator.language || navigator.userLanguage).substr(0, 2); // 初期レベルの生成 THIEF.global.actLV = THIEF.util.createLevel(); // HTML タグ初期化 THIEF.html.init(); THIEF.html.addDebugMessage('初期化(ターン0)を開始...'); // ヘルプの表示 //THIEF.html.showCommandHelp(); // テスト用コードの実行 THIEF.util.test(); THIEF.html.refresh(); // 1 ターン目開始 THIEF.global.turn = 0; //THIEF.util.updateStatus(); THIEF.html.addDebugMessage('...初期化(ターン0)を完了。'); THIEF.util.next(); }; THIEF.util.test = function() { THIEF.global.adventurer = Object.create(THIEF.type.Human); THIEF.global.adventurer.color = 'red'; THIEF.global.adventurer.next = THIEF.global.adventurer.inputWait; THIEF.global.adventurer.name = { ja : '冒険者', en : 'Adventurer' }; THIEF.global.adventurer.symbol = '@'; THIEF.global.adventurer.inventoryHeight = 1; THIEF.global.adventurer.inventoryLength = 10; THIEF.global.adventurer.inventoryWidth = 10; THIEF.global.adventurer.inventoryCellSize = 1; THIEF.global.adventurer.hp = 100; THIEF.global.adventurer.ct = 100; THIEF.global.actLV.addToInventory(THIEF.global.adventurer); var tmp2; tmp2 = Object.create(THIEF.type._item._weapon.TestDugger); tmp2.alphabet = 'k'; THIEF.global.adventurer.addToInventory(tmp2); THIEF.util.spawn(THIEF.type._life._humanoid.Daemon); THIEF.util.spawn(THIEF.type._life._humanoid.Daemon); THIEF.util.spawn(THIEF.type._life._humanoid.Daemon); }; THIEF.util.next = function () { THIEF.html.clearDebugMessage(); THIEF.html.addDebugMessage('ターン:' + THIEF.global.turn + ' を開始...'); if(THIEF.util.step()){ //noinspection DynamicallyGeneratedCodeJS setTimeout(THIEF.util.next, 100); THIEF.html.addDebugMessage('...ターン:' + THIEF.global.turn + ' を完了。'); } else { //THIEF.util.updateStatus(); THIEF.html.addDebugMessage('...ターン:' + THIEF.global.turn + ' を中断。'); } }; THIEF.util.step = function () { var completion = true; var compCounter = 15; return function () { if(completion){ THIEF.global.turn++; THIEF.html.addDebugMessage('通知を開始...'); THIEF.global.actLV.notify(); THIEF.html.addDebugMessage('...通知を完了'); // 各レベルに実施させること if ( Math.random() > 0.9 ) { THIEF.util.spawn(THIEF.type._life._humanoid.Daemon); } } //THIEF.util.updateStatus(); THIEF.html.addDebugMessage('アクティブになったオブジェクトの処理を実施...'); completion = THIEF.global.actLV.action(); THIEF.html.addDebugMessage('...アクティブになったオブジェクトの処理を完了'); THIEF.util.updateStatus(); if(compCounter < 0){ compCounter = 15; completion = false; THIEF.html.addDebugMessage('無限ループにならないように、15回以上ループするなら強制的にブレイク。') } else if(completion){ compCounter--; } else { compCounter = 15; } return completion; }; }(); THIEF.util.updateStatus = function () { // 何かが行動するたびにステータス表示を更新 THIEF.html.addDebugMessage('ステータス画面の更新開始...'); for (var i = 0; i < THIEF.conf.statusLineFormat.length; i++) { var line = THIEF.conf.statusLineFormat[i]; // ${xxx} は動的変数として、内部の構文を解析する // 変数内部は、通常の変数のように ドット で区切る // %xxx@yyy@zzz% と表記されている部分は関数として処理する // @ で区切られた部分は関数の引数とする // 例:${THIEF.global.adventurer.%get@name%} ♥:${THIEF.global.adventurer.%get@hp%} // 変数の取得 var variables = THIEF.conf.statusLineFormat[i].match(/\$\{[A-Za-z0-9_$.%@]+\}/g); for (var j = 0; j < variables.length; j++) { // ${ と } を削除 var step1 = variables[j].slice(2, variables[j].length - 1); // ピリオドで分割 var step2 = step1.split('.'); // 値格納用変数 var val = THIEF; // 確認 // 0 は THIEF なのでパス。(現在は一応確認) if (step2[0] !== 'THIEF') { alert('変数指定の方法が間違っています。'); } for (var k = 1; k < step2.length; k++) { // 変数処理 if (step2[k].search(/^%.+%$/) === -1) { //THIEF.html.addDebugMessage(val + ' -> ' + step2[k]); val = val[step2[k]]; //THIEF.html.addDebugMessage(val) // 関数処理 } else { // 前後の % を削除し、@で分割 var step3 = step2[k].slice(1, step2[k].length - 1).split('@'); var args = []; var func = step3[0]; for (var l = 1; l < step3.length; l++) { args.push(step3[l]); } val = val[func].apply(val, args); } } if(typeof val === 'undefined'){ THIEF.html.addDebugMessage(step1 + ' は定義されていない'); } else { THIEF.html.addDebugMessage(step1 + ' = ' + val.toString()); } line = line.replace(variables[j], val); } document.getElementById(THIEF.conf.id + 'Status' + i).innerHTML = line; } THIEF.html.addDebugMessage('...ステータス画面の更新完了。'); }; THIEF.util.getKeyCode = function(e) { var key = THIEF.KEY; // Browser bug fix if (!e) { //noinspection AssignmentToFunctionParameterJS e = window.event; } // キーコード取得 var code = 0; if (document.all) { code = event.keyCode; } else if (document.getElementById) { code = (e.keyCode === 0) ? e.charCode : e.keyCode; } else { // document.layers code = e.which; } // 基本的にはブラウザに処理を渡さない var block = true; // コンビネーションキー "だけ" 押されたイベントは無視 // ブラウザにも処理を回す if (code === key.Shift || code === key.Ctrl || code === key.Alt) { code = 0; block = false; // 非 Shift押下時処理 } else { if (!e.shiftKey) { switch (code) { // 方向キー用の調整 case key.Up: code = key.k; break; case key.Down: code = key.j; break; case key.Left: code = key.h; break; case key.Right: code = key.l; break; case key.Home: code = key.y; break; case key.End: code = key.b; break; case key.PageUp: code = key.u; break; case key.PageDown: code = key.n; break; // コピペ用 case key.a: case key.c: case key.v: if (e.ctrlKey) { block = false; code = 0; } break; // ファンクションキーはブラウザに処理を回す // 他の文字とコードはかぶっているが問題なしとする case key.F1: case key.F2: case key.F3: case key.F4: case key.F5: case key.F6: case key.F7: case key.F8: case key.F9: case key.F10: case key.F11: case key.F12: block = false; //code = 0; break; default: break; } } } // ブラウザへのイベント伝播を防止 if (block) { if (e.preventDefault) { e.preventDefault(); e.stopPropagation(); } e.returnValue = false; e.cancelBubble = true; } return code; }; THIEF.util.createLevel = function() { var lv = Object.create(THIEF.type.Level); lv.mapRefreshPointList = []; lv.inventory = THIEF.util.createMap(THIEF.conf.mapWidth, THIEF.conf.mapLength); lv.set(THIEF.E.name, {ja:'テストレベル', en:'Practice'}); lv.set(THIEF.E.inventoryWidth, THIEF.conf.mapWidth); lv.set(THIEF.E.inventoryLength, THIEF.conf.mapLength); lv.set(THIEF.E.inventoryHeight, THIEF.conf.mapHeight); lv.inventoryCellSize = 1; return lv; }; THIEF.util.createMap = function(width, height) { var i, j; var map = []; // マップ作成、外壁を初期化 for (i = 0; i < width; i++) { var line = []; for (j = 0; j < height; j++) { line[j] = []; if (i === 0 || j === 0 || i === (width - 1) || j === (height - 1)) { line[j].push(THIEF.type.Wall.NonDiggable); } } map[i] = line; } // マップ分割 var rooms = Math.floor(Math.random() * (width + height) / 10) + (width + height) / 20; var anchors = []; var roomEdges = [ {x:1, y:1} ]; // 左上は常に部屋の角 var count = 0; var roop = 0; var roopLimit = 300; // 300 回くらい試行して駄目ならあきらめる while (count < rooms && roop < roopLimit) { roop++; //アンカーを計算(周囲 1*2 マスと、さらに 2 マス(部屋壁の厚み分) var ax = Math.floor((Math.random() * (width - width * 0.1 - 4) ) + width * 0.1 + 2); var ay = Math.floor((Math.random() * (height - height * 0.1 - 4) ) + height * 0.1 + 2); // アンカーに何かあればやり直し if (map[ax][ay].length !== 0) { continue; } // 距離チェック var lx = 0; var hx = 0; var ly = 0; var hy = 0; // 左端までの距離 for (i = ax - 1; i > 0; i--) { if (map[i][ay].length === 0) { lx++; } else { break; } } // 右端までの距離 for (i = ax + 1; i < width; i++) { if (map[i][ay].length === 0) { hx++; } else { break; } } // 上端までの距離 for (i = ay - 1; i > 0; i--) { if (map[ax][i].length === 0) { ly++; } else { break; } } // 下端までの距離 for (i = ay + 1; i < height; i++) { if (map[ax][i].length === 0) { hy++; } else { break; } } // 壁、または分割線までの最小距離 var mx = Math.min(lx, hx); var my = Math.min(ly, hy); // 狭すぎるならやり直し // 幅(壁含まず)が3マス未満 // 3x5 未満 if (Math.max(mx, my) < 5 || (Math.max(mx, my) === 5 && Math.min(mx, my) < 7 )) { continue; } // 最初は縦、次は横の方がなんとなく綺麗になるようだ if ((count % 2 === 0 && my > mx) || (count % 2 === 1 && my <= mx)) { continue; } // 一般的にマップ全体は横幅の方が長いと仮定している // 壁までの距離が短い方に伸ばすように分割線を引く // 長い方に伸ばすように引くと部屋が小さくなるため map[ax][ay].push(THIEF.type.Floor.Dark); anchors.push({x:ax, y:ay}); if (my < mx) { // 縦に引く for (i = ay - 1; i >= 0; i--) { if (map[ax][i].length === 0) { map[ax][i].push(THIEF.type.Floor.Dark); } else { roomEdges.push({x:ax + 1, y:i + 1}); break; } } for (i = ay + 1; i < height; i++) { if (map[ax][i].length === 0) { map[ax][i].push(THIEF.type.Floor.Dark); } else { break; } } } else { // 横に引く for (i = ax - 1; i >= 0; i--) { if (map[i][ay].length === 0) { map[i][ay].push(THIEF.type.Floor.Dark); } else { roomEdges.push({x:i + 1, y:ay + 1}); break; } } for (i = ax + 1; i < width; i++) { if (map[i][ay].length === 0) { map[i][ay].push(THIEF.type.Floor.Dark); } else { break; } } } count++; } if (roop === roopLimit) { // THIEF.html.addMessage(roop); } // 部屋を作成 var centers = []; for (var index = 0; index < roomEdges.length; index++) { var point = roomEdges[index]; var x = point.x; var y = point.y; // 分割した領域のサイズを取得 var roomWidth = 0; var roomHeight = 0; for (i = x; i < width; i++) { if (map[i][y].length === 0) { roomWidth++; } else { break; } } for (i = y; i < height; i++) { if (map[x][i].length === 0) { roomHeight++; } else { break; } } // 部屋の大きさ決定 var startX = Math.floor(Math.random() * (roomWidth / 3)); var startY = Math.floor(Math.random() * (roomHeight / 3)); var endX = Math.floor(Math.random() * (roomWidth / 3) + roomWidth * 2 / 3); var endY = Math.floor(Math.random() * (roomHeight / 3) + roomHeight * 2 / 3); var cx = x + startX + Math.floor((endX - startX) / 2); var cy = y + startY + Math.floor((endY - startY) / 2); centers.push({x:cx, y:cy}); // 狭すぎるならちょっと広げる if (endX - startX < 4) { startX--; endX++; } if (endY - startY < 4) { startY--; endY++; } // 部屋作成 for (i = startX; i < endX; i++) { for (j = startY; j < endY; j++) { if (i === startX || i === (endX - 1) || j === startY || j === (endY - 1)) { map[x + i][y + j].push(THIEF.type.Wall.Normal); } else { map[x + i][y + j].push(THIEF.type.Floor.Lit); } } } } // 今は仮の処理として、部屋の中心から(どこかの)アンカーに向かって経路を引く // アンカーが一個足りないのでマップの中心として追加 anchors.push({x:Math.floor(THIEF.conf.mapWidth / 2), y:Math.floor(THIEF.conf.mapLength / 2)}); for (i = 0; i < anchors.length; i++) { var vx = Math.sign(anchors[i].x - centers[i].x); var vy = Math.sign(anchors[i].y - centers[i].y); if (centers[i].x < THIEF.conf.mapWidth / 2 && vx === -1 || centers[i].x > THIEF.conf.mapWidth / 2 && vx === 1) { vx *= -1; } if (centers[i].y < THIEF.conf.mapLength / 2 && vy === -1 || centers[i].y > THIEF.conf.mapLength / 2 && vy === 1) { vy *= -1; } // 移動距離 var dx = 0; var dy = 0; var counter = 0; var door = 0; while (counter >= 0) { counter++; // 縦横順番に移動 if (counter % 2 === 0) { dx += vx; } else { dy += vy; } var pix = map[centers[i].x + dx][centers[i].y + dy]; var obj = pix.getLast(); if (typeof obj === 'undefined') { // 道を作る pix.push(THIEF.type.Floor.Dark); if (door > 0) { // ドアを作った後はひたすらまっすぐ counter++; } } else if (obj === THIEF.type.Wall.Normal) { // ドアを作る pix.remove(THIEF.type.Wall.Normal); pix.push(THIEF.type.Floor.Lit); if (door === 2) { break; // 二回ドアを作ったら終了 } counter++; door++; } else if (obj === THIEF.type.Floor.Dark || obj === THIEF.type.Wall.NonDiggable) { break; } } } // 上下左右に二つ以上の通路、または扉がなければ削除 var cnt = 0; var around; // 上から for (i = 1; i < width - 1; i++) { for (j = 1; j < height - 1; j++) { if (map[i][j].getLast() === THIEF.type.Floor.Dark) { cnt = 0; around = map[i - 1][j].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[i + 1][j].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[i][j - 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[i][j + 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } if (cnt < 2) { map[i][j].remove(THIEF.type.Floor.Dark); } } } } // 下から for (i = 1; i <= width - 1; i++) { for (j = height - 1; j > 1; j--) { if (map[i][j].getLast() === THIEF.type.Floor.Dark) { cnt = 0; around = map[i - 1][j].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[i + 1][j].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[i][j - 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[i][j + 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } if (cnt < 2) { map[i][j].remove(THIEF.type.Floor.Dark); } } } } // 左から for (i = 1; i < height - 1; i++) { for (j = 1; j < width - 1; j++) { if (map[j][i].getLast() === THIEF.type.Floor.Dark) { cnt = 0; around = map[j - 1][i].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[j + 1][i].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[j][i - 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[j][i + 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } if (cnt < 2) { map[j][i].remove(THIEF.type.Floor.Dark); } } } } // 右から for (i = 1; i < height - 1; i++) { for (j = width - 1; j > 1; j--) { if (map[j][i].getLast() === THIEF.type.Floor.Dark) { cnt = 0; around = map[j - 1][i].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[j + 1][i].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[j][i - 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } around = map[j][i + 1].getLast(); if (around === THIEF.type.Floor.Dark || around === THIEF.type.Wall.Door || around === THIEF.type.Floor.Lit) { cnt++; } if (cnt < 2) { map[j][i].remove(THIEF.type.Floor.Dark); } } } } // 残りを初期化 for (i = 0; i < width; i++) { for (j = 0; j < height; j++) { if (map[i][j].length === 0) { map[i][j].push(THIEF.type.Wall.Hidden); } } } return map; }; THIEF.util.spawn =function (obj) { THIEF.html.addDebugMessage('湧き処理を開始...'); var monster = null; THIEF.html.addDebugMessage('オブジェクトの複製'); if ( typeof obj === 'undefined'){ // 条件に応じた対象を選択すること monster = Object.create(THIEF.type._life._humanoid.Daemon); } else { monster = Object.create(obj); } // ??? /* monster.inventoryHeight = 1; monster.inventoryLength = 10; monster.inventoryWidth = 10; monster.inventoryCellSize = 1; */ // 空きスペースの検索条件 var point; for(var i=0; i<10; i++){ var x = Math.round(Math.random() * THIEF.global.actLV.get(THIEF.E.inventoryWidth)); var y = Math.round(Math.random() * THIEF.global.actLV.get(THIEF.E.inventoryLength)); point = THIEF.global.actLV.getInventoryFreeSpace(monster, x, y); if(typeof point.x === 'number' && typeof point.y === 'number'){ break; } } if(typeof point.x !== 'number' && typeof point.y !== 'number'){ point = THIEF.global.actLV.getInventoryFreeSpace(monster); } THIEF.global.actLV.addToInventory(monster, point.x, point.y); THIEF.html.refreshXy(monster.x, monster.y); THIEF.html.addDebugMessage('...湧き処理を完了') }; THIEF.html = {}; THIEF.html.setXy = function(x, y, text) { if (0 <= x && x < THIEF.conf.mapWidth && 0 <= y && y < THIEF.conf.mapLength) { document.getElementById(THIEF.conf.id + x + '_' + y).innerHTML = text; } }; THIEF.html.refreshXy = function(x, y) { var obj = THIEF.global.actLV.inventory[x][y].getLast(); if (obj.color) { THIEF.html.setXy(x, y, '' + obj.symbol + ''); } else { THIEF.html.setXy(x, y, obj.symbol); } }; THIEF.html.refresh = function() { THIEF.html.addDebugMessage('再描画を開始...'); for (var i = 0; i < THIEF.conf.mapWidth; i++) { for (var j = 0; j < THIEF.conf.mapLength; j++) { THIEF.html.refreshXy(i, j); } } THIEF.html.addDebugMessage('...再描画を完了。'); }; THIEF.html.setInput = function(text) { document.getElementById(THIEF.conf.id + 'Input').innerHTML = text; }; THIEF.html.addInput = function(text) { document.getElementById(THIEF.conf.id + 'Input').innerHTML += text; }; THIEF.html.addMessage = function(text) { if (typeof text === 'undefined') { text = ''; } var log = {}; log.text = text; log.turn = THIEF.global.turn; THIEF.global.hist.push(log); if (THIEF.global.hist.length > THIEF.conf.messageHistorySize * 2) { THIEF.global.hist = THIEF.global.hist.slice(THIEF.conf.messageHistorySize); } // line += ' ...↵'; document.getElementById(THIEF.conf.id + 'Message' + (THIEF.conf.messageLines - 1)).innerHTML = text; }; THIEF.html.clearMessage = function() { for (var i = 0; i < THIEF.conf.messageLines; i++) { document.getElementById(THIEF.conf.id + 'Message' + i).innerHTML = ' '; } }; THIEF.html.clearInfomation = function() { document.getElementById(THIEF.conf.id + 'Infomation').innerHTML = ''; }; THIEF.html.addInfomation = function(text) { document.getElementById(THIEF.conf.id + 'Infomation').innerHTML += text + '
'; }; //noinspection JSUnusedGlobalSymbols THIEF.html.addDebugMessage = function() { var indent = ''; return function(text) { // 文字列が ... から開始する場合にはインデントを減らす if (text.match(/^\.\.\./) && indent.length > 0) { indent = indent.slice(24); } if (THIEF.conf.debugmode) { document.getElementById(THIEF.conf.id + 'Debug').innerHTML += indent + text + '
'; document.getElementById(THIEF.conf.id + 'Debug').scrollTop = 0; //document.getElementById(THIEF.conf.id + 'Debug').scrollTop = 65535; //document.getElementById(THIEF.conf.id + 'Debug').offsetTop = 65535; } // 文字列が ... で終わる場合にはインデントを増やす if (text.match(/\.\.\.$/)) { indent += '    '; } } }(); THIEF.html.clearDebugMessage = function() { if (THIEF.conf.debugmode) { document.getElementById(THIEF.conf.id + 'Debug').innerHTML = ''; } }; THIEF.html.showCommandHelp = function() { var help = ''; help += '\n'; help += '\n'; var com = []; for (var name in THIEF.type.$.manual) { com.push(name); } com.sort(function(a, b) { var x = a; var y = b; if (a === '#'.charCodeAt(0).toString()) { x -= 70000; } if (b === '#'.charCodeAt(0).toString()) { y -= 70000; } if (THIEF.KEY.a <= a && a <= THIEF.KEY.z) { x -= 50000; } if (THIEF.KEY.a <= b && b <= THIEF.KEY.z) { y -= 50000; } if (THIEF.KEY.A <= a && a <= THIEF.KEY.Z) { x -= 20000; } if (THIEF.KEY.A <= b && b <= THIEF.KEY.Z) { y -= 20000; } return x - y; }); for (var i = 0; i < com.length; i++) { help += '\n'; } help += '
Command Help
' + String.fromCharCode(com[i]) + '' + THIEF.type.$.manual[com[i]].toString().slice(THIEF.type.$.manual[com[i]].toString().indexOf('this.') + 5, THIEF.type.$.manual[com[i]].toString().lastIndexOf('(')) + '
\n'; document.getElementById(THIEF.conf.id + 'Debug').innerHTML = help; }; THIEF.html.init = function() { var line = ''; var i, j; // スタイルシート挿入用メソッド作成 var style = document.createElement('style'); style.setAttribute('type', 'text/css'); document.getElementsByTagName('head')[0].appendChild(style); var sheet; if (typeof document.createStyleSheet === 'undefined') { sheet = style.sheet; sheet.addCSS = function(selector, property, value) { sheet.insertRule(selector + '{' + property + ':' + value + ';}', sheet.cssRules.length); }; } else { sheet = document.createStyleSheet(); sheet.addCSS = function(selector, property, value) { sheet.addRule(selector, '{' + property + ':' + value + ';}'); }; } // スタイルシート適応 var root = THIEF.conf.id; var main = THIEF.conf.id + 'Main'; // Input, Message, Map, Status var inpt = THIEF.conf.id + 'Input'; // 入力欄 var mesg = THIEF.conf.id + 'Message'; // メッセージ欄(入力上部) var maps = THIEF.conf.id + 'Map'; // マップ var stus = THIEF.conf.id + 'Status'; // ステータス var info = THIEF.conf.id + 'Infomation'; // 情報出力(インベントリの内容など) var dbug = THIEF.conf.id + 'Debug'; // デバッグ情報 sheet.addCSS('#' + root, 'color', THIEF.conf.textColor); sheet.addCSS('#' + root, 'background-color', THIEF.conf.bgColor); sheet.addCSS('#' + root, 'font-family', THIEF.conf.fontFace); sheet.addCSS('#' + root, 'letter-spacing', '0px'); sheet.addCSS('#' + root, 'line-height', '1'); sheet.addCSS('#' + main, 'margin', '1em'); sheet.addCSS('#' + main, 'float', THIEF.conf.mainWindowPosition); sheet.addCSS('#' + maps, 'text-align', 'center'); sheet.addCSS('#' + maps, 'vertical-align', 'middle'); sheet.addCSS('#' + maps + ' table', 'border', '1px solid ' + THIEF.conf.textColor); sheet.addCSS('#' + maps + ' table', 'border-collapse', 'collapse'); sheet.addCSS('#' + maps + ' table', 'border-spacing', '0px'); sheet.addCSS('#' + maps + ' td', 'border', THIEF.conf.gridStyle); sheet.addCSS('#' + maps + ' td', 'margin', '0px'); sheet.addCSS('#' + maps + ' td', 'padding', '0px'); sheet.addCSS('#' + maps + ' td', 'color', THIEF.conf.textColor); // テーブル内文字色には必須? sheet.addCSS('#' + info, 'border', THIEF.conf.gridStyle); sheet.addCSS('#' + info, 'height', THIEF.conf.mapLength + 'em'); sheet.addCSS('#' + info, 'overflow', THIEF.conf.msgOverflow); sheet.addCSS('#' + info, 'padding', '1em'); sheet.addCSS('#' + dbug, 'border', THIEF.conf.gridStyle); sheet.addCSS('#' + dbug, 'height', THIEF.conf.debugMessageHeight); sheet.addCSS('#' + dbug, 'overflow', 'scroll'); // メイン画面の位置決め line += '
\n'; //ステータス //メッセージ if (THIEF.conf.statusPosition === 'top') { line += '
\n'; for (i = 0; i < THIEF.conf.statusLineFormat.length; i++) { line += '
\n'; } line += '
\n'; } if (THIEF.conf.messagePosition === 'top') { line += '
\n'; for (i = 0; i < THIEF.conf.messageLines; i++) { line += '
 
\n'; } line += '
\n'; // キー入力画面 line += '
 
\n'; } // マップ line += '
\n'; line += '\n'; for (i = 0; i < THIEF.conf.mapLength; i++) { line += ''; for (j = 0; j < THIEF.conf.mapWidth; j++) { line += ''; } line += '\n'; } line += '
#
\n'; line += '
\n'; //ステータス //メッセージ if (THIEF.conf.statusPosition === 'bottom') { line += '
\n'; for (i = 0; i < THIEF.conf.statusLineFormat.length; i++) { line += '
\n'; } line += '
\n'; } if (THIEF.conf.messagePosition === 'bottom') { line += '
\n'; for (i = 0; i < THIEF.conf.messageLines; i++) { line += '
メッセージライン:' + i + '
\n'; } line += '
\n'; // キー入力画面 line += '
 
\n'; } // メイン画面終了 line += '
\n'; // インフォメーション画面 line += '
\n'; // 後処理 // メッセージの回り込みを解除 // span を使うと回りこみの影響で背景色が変になるので注意 line += '

\n'; // デバッグ画面 if (THIEF.conf.debugmode) { line += '

Debug Info

\n'; line += '
\n'; } document.getElementById(THIEF.conf.id).innerHTML = line; THIEF.html.refresh(); }; THIEF.type = {}; THIEF.type.$ = Object.create(THIEF.command); THIEF.type.$.active = false; // turn THIEF.type.$.name = 'Nameless'; THIEF.type.$.displayName = function() { return this.get(THIEF.E.name) + '(' + this.get(THIEF.E.symbol) + ')' }; //THIEF.type.$.territory = false; // 自分と同じインベントリセルに対する侵入を拒むか THIEF.type.$.symbol = '╳'; // 未登録用印(X に近い) THIEF.type.$.color = undefined; THIEF.type.$.decayable = false; THIEF.type.$.portable = false; THIEF.type.$.mergeable = false; THIEF.type.$.stackable = false; // インベントリ内で同じものが重ねられるか THIEF.type.$.ct = 0; /* THIEF.type.$.getLocalizedText = function(prop) { var text = null; for (var i = 0; i < THIEF.conf.languagePriolity.length; i++) { if (THIEF.conf.languagePriolity[i] === 'LOCALE') { text = this[prop][THIEF.conf.language]; } else { text = this[prop][THIEF.conf.languagePriolity[i]]; } if (typeof text !== 'undefined') { break; } } if (typeof text === 'undefined') { text = this[prop]; } return text; }; */ THIEF.type.$.get = function (param) { var val; if (typeof this[param] === 'function') { val = this[param](); } else if (this[param]) { if (this[param][THIEF.conf.language]) { val = this[param][THIEF.conf.language]; } else { val = this[param]; for (var i = 0; i < THIEF.conf.languagePriolity.length; i++) { if (this[param][THIEF.conf.languagePriolity[i]]) { val = this[param][THIEF.conf.languagePriolity[i]]; break; } } } } return val; }; THIEF.type.$.set = function (param, val) { this[param] = val; }; THIEF.type.$.removeFromInventory = function(obj) { var objX = obj.x; var objY = obj.y; THIEF.html.addDebugMessage(obj.get(THIEF.E.displayName) + 'を' + this.get(THIEF.E.displayName) + 'のインベントリ座標[' + obj.x + ', ' + obj.y + ']から除外...'); var shapeX = Math.ceil(obj.get(THIEF.E.shapeWidth) / this.get(THIEF.E.inventoryCellSize)) || 1; var shapeY = Math.ceil(obj.get(THIEF.E.shapeHeight) / this.get(THIEF.E.inventoryCellSize)) || 1; if (obj.myOwner === this) { obj.myOwner = null; obj.x = undefined; obj.y = undefined; for (var i = 0; i < shapeX; i++) { for (var j = 0; j < shapeY; j++) { THIEF.html.addDebugMessage('座標[' + (objX + i) + ', ' + (objY + j) + ']から除外'); this.inventory[objX + i][objY + j].remove(obj); THIEF.html.refreshXy(objX + i, objY + j); } } } THIEF.html.addDebugMessage('...' + obj.get(THIEF.E.displayName) + 'を' + this.get(THIEF.E.displayName) + 'のインベントリ座標[' + objX + ', ' + objY + ']から除外完了。'); return true; }; THIEF.type.$.addToInventory = function(obj, x, y) { var result = false; THIEF.html.addDebugMessage(obj.get(THIEF.E.displayName) + 'を' + this.get(THIEF.E.displayName) + 'のインベントリ座標[' + x + ', ' + y + ']に追加処理を開始...'); var target = this.getInventoryFreeSpace(obj, x, y); if (target.x >= 0 && target.y >= 0) { obj.x = target.x; obj.y = target.y; obj.myOwner = this; THIEF.html.addDebugMessage(target.x + ', ' + target.y + 'を基準に ' + target.width + 'x' + target.len + ' のサイズとして追加'); for (var i = target.x; i < target.x + target.width; i++) { for (var j = target.y; j < target.y + target.len; j++) { if (!this.inventory) { this.inventory = []; } if (!this.inventory[i]) { this.inventory[i] = []; } if (!this.inventory[i][j]) { this.inventory[i][j] = []; } var alphabets = this.getInventoryAlphabets(); if (typeof obj.get(THIEF.E.alphabet) === 'string' && alphabets.indexOf(obj.get(THIEF.E.alphabet)) === -1) { //; } else { var alp = this.getInventoryNonExistAlphabet(); if (typeof alp === 'undefined') { alert('アルファベット関係のバグ'); } else { obj.set(THIEF.E.alphabet, this.getInventoryNonExistAlphabet()); } } this.inventory[i][j].push(obj); THIEF.html.addDebugMessage('[' + i + ', ' + j + ']に' + obj.get(THIEF.E.alphabet) + 'として追加'); result = true; } } } else { THIEF.html.addDebugMessage('追加可能なスペースがない。'); } THIEF.html.addDebugMessage('...' + obj.get(THIEF.E.displayName) + 'を' + this.get(THIEF.E.displayName) + 'のインベントリ座標[' + x + ', ' + y + ']に追加処理を完了。(return : ' + result + ')'); return result; }; THIEF.type.$.getInventoryFreeSpace = function(obj, _x, _y) { var invCellSize = this.get(THIEF.E.inventoryCellSize) || 10; var invWidth = this.get(THIEF.E.inventoryWidth) || 0; var invLength = this.get(THIEF.E.inventoryLength) || 0; var invHeight = this.get(THIEF.E.inventoryHeight) || 0; var objShapeWight = obj.get(THIEF.E.shapeWidth) || Math.ceil(obj.get(THIEF.E.siz) / 4) || 1; var objShapeLength = obj.get(THIEF.E.shapeHeight) || Math.ceil(obj.get(THIEF.E.siz) / 4) || 1; var objInvShapeWight = Math.ceil(objShapeWight / invCellSize); var objInvShapeLength = Math.ceil(objShapeLength / invCellSize); var resultAnc = {}; var startX = _x || 0; var startY = _y || 0; var once = (typeof _x === "number" || typeof _y === "number"); THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + 'のインベントリ(' + invLength + ', ' + invWidth + ', ' + invHeight + ')の座標[' + _x + ', ' + _y + ']に' + obj.get(THIEF.E.displayName) + '(' + objInvShapeWight + ', ' + objInvShapeLength + ')として格納できるか確認を開始...'); var free; outloop : for (var ancY = startY; ancY < invLength; ancY++) { //alert(ancY + '行目を処理...'); for (var ancX = startX; ancX < invWidth; ancX++) { //alert(ancX + ', ' + ancY); free = true; //THIEF.html.addDebugMessage(ancX + ', ' + ancY + 'を確認...'); inloop : for (var targetY = ancY; targetY < ancY + objInvShapeLength; targetY++) { for (var targetX = ancX + objInvShapeWight - 1; targetX >= ancX; targetX--) { if (this.inventory && this.inventory[targetX] && this.inventory[targetX][targetY]) { if (this.inventory[targetX][targetY].length <= invHeight) { var lastObj = this.inventory[targetX][targetY].getLast(); if (obj.get(THIEF.E.stackable) || typeof lastObj === 'undefined' || lastObj.get(THIEF.E.stackable) /* || !lastObj.get(THIEF.E.mergeable) */) { if(lastObj){ THIEF.html.addDebugMessage('[' + targetX + ', ' + targetY + ']にある' + lastObj.get(THIEF.E.displayName) + 'には重ねられる。'); } else { THIEF.html.addDebugMessage('[' + targetX + ', ' + targetY + ']には何も無いので重ねられる。'); } } else { free = false; ancX = targetX; //THIEF.html.addDebugMessage(targetX + ', ' + targetY + 'にある' + lastObj.get(THIEF.E.name) + 'には重ねられない'); break inloop; } } else { free = false; ancX = targetX; //THIEF.html.addDebugMessage(targetX + ', ' + targetY + ' は高さが足りないからダメ'); break inloop; } } else { THIEF.html.addDebugMessage(targetX + ', ' + targetY + ' は空'); } } } if (free) { resultAnc.x = ancX; resultAnc.y = ancY; resultAnc.width = objInvShapeWight; resultAnc.len = objInvShapeLength; break outloop; } if (once) { break outloop; } } } THIEF.html.addDebugMessage('...' + obj.get(THIEF.E.displayName) + '(' + objInvShapeWight + ', ' + objInvShapeLength + ')として格納できるか確認を完了。'); return resultAnc; }; THIEF.type.$.attackedBy = function(obj) { THIEF.html.addDebugMessage(obj.get(THIEF.E.displayName) + ' による ' + this.get(THIEF.E.displayName) + ' への攻撃処理を開始...'); var damege = obj.get(THIEF.E.atk) || (1 + Math.round(Math.random() * 9)); THIEF.html.addDebugMessage('ベースダメージを ' + damege + 'とする。'); THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + ' HP : ' + this.get(THIEF.E.hp) + ' -> ' + (this.get(THIEF.E.hp) - damege) + 'とする。'); this.hp -= damege; THIEF.html.addMessage(this.get(THIEF.E.displayName) + 'は ' + damege + ' のダメージを受けた'); obj.ct -= 100; if( this.get(THIEF.E.hp) <= 0 ){ THIEF.html.addDebugMessage('死亡処理を開始...'); THIEF.html.addMessage(this.get(THIEF.E.displayName) + 'は、破壊された。'); THIEF.global.actLV.removeFromInventory(this); this.next = function(){return true}; THIEF.html.addDebugMessage('...死亡処理を完了。') } THIEF.html.addDebugMessage('...攻撃処理を完了。'); return true; }; THIEF.type.$.addParam = function(param) { for (var name in param) { if (typeof this[name] === 'undefined' || typeof this[name] === 'null') { this[name] = param[name]; } else { this[name] += param[name]; } } }; THIEF.type.$.getInventoryObjects = function(request) { var array = []; // 必ずしも inventory の配列を完全に持っているとは限らないので注意すること if (!!this.inventory) { for (var i = this.inventory.length; i >= 0; i--) { for (var j = this.inventory[i].length; j >= 0; j--) { for (var k = this.inventory[i][j].length; k >= 0; k--) { var item = this.inventory[i][j][k]; if (item.checkParam(request)) { array.push(item); } } } } } return array; }; THIEF.type.$.getInventoryXyLastObject = function(x, y) { var obj; // 必ずしも inventory の配列を完全に持っているとは限らないので注意すること if (this.inventory && this.inventory[x] && this.inventory[x][y]) { obj = this.inventory[x][y].getLast(); } return obj; }; // ループ処理を加えること THIEF.type.$.getInventoryAlphabets = function() { var alphabets = []; if (typeof this.inv !== 'undefined') { for (var i = 0; i < this.inv.length; i++) { alphabets.push(this.inv[i].alphabet); } } return alphabets; }; THIEF.type.$.getInventoryNonExistAlphabet = function() { // 常にアルファベットの先頭が利用されないようにしている var key = THIEF.KEY; var index = key.a; return function() { var alphabets = this.getInventoryAlphabets(); var counter = 0; while (alphabets.indexOf(String.fromCharCode(index)) !== -1 && counter < 52) { counter++; index++; if (index === (key.z + 1)) { index = key.A; } else { if (index === (key.Z + 1)) { index = key.a; } } } var alphabet; if (counter < 52) { alphabet = String.fromCharCode(index); } index++; return alphabet; }; }(); THIEF.type.$.checkParam = function(request) { var result = true; for (var name in request) { if (typeof name !== 'function') { if (this[name] !== request[name]) { result = false; break; } } } return result; }; // items 配列を渡してカリー化(?) THIEF.type.$.selecter = function(objs, exec, immediately, abc) { var key = THIEF.KEY; var items = []; var selected = []; var targets = []; var i, j; THIEF.html.addDebugMessage('セレクターを生成'); for (i = 0; i < objs.length; i++) { THIEF.html.addDebugMessage('セレクターターゲット:' + objs[i].get(THIEF.E.displayName)); if (objs[i] !== this && objs[i].portable && objs[i].get(THIEF.E.displayName)) { items.push(objs[i]); } } // root_abc var alphabetIndex = key.a; // アイテム出力 for (i = 0; i < THIEF.conf.itemSort.length; i++) { //アイテムがあるか確認 var first = true; for (j = 0; j < items.length; j++) { if (THIEF.conf.itemSort[i] === items[j].symbol) { if (first) { first = false; THIEF.html.addInfomation('' + items[j].get(THIEF.E.symbolName) + ''); } var alphabet; if (abc) { alphabet = String.fromCharCode(alphabetIndex); alphabetIndex++; } else { alphabet = items[j].alphabet || this.getInventoryNonExistAlphabet(); if (alphabet === null) { // ページ切り替え break; } items[j].alphabet = alphabet; } THIEF.html.addInfomation(alphabet + ' - ' + items[j].get(THIEF.E.displayName)); targets[alphabet] = items[j]; } } } // 選択用関数返却 return function() { var finish = false; switch (THIEF.global.keycode) { case '*'.charCodeAt(0): /* if (immediately) { //THIEF.html.addMessage('複数選択はできません'); } else { // } */ break; case key.Esc: finish = true; selected.length = 0; break; case key.Space: break; case key.Enter: finish = true; this.action = THIEF.type.$.action; break; default: var item = targets[String.fromCharCode(THIEF.global.keycode)]; var itemID = THIEF.conf.id + '_' + String.fromCharCode(THIEF.global.keycode); if (typeof item !== 'undefined') { if (document.getElementById(itemID).innerHTML === ' - ') { document.getElementById(itemID).innerHTML = ' + '; selected.push(item); } else { document.getElementById(itemID).innerHTML = ' - '; selected.remove(item); } } if (immediately) { finish = true; } break; } var result = false; if (finish) { // 画面クリア THIEF.html.clearInfomation(''); // アクションを元に戻す this.action = THIEF.type.$.action; // 選択後のアクションを実行 result = exec(selected); } return result; }; }; THIEF.type.$.cpu = function() { THIEF.html.addDebugMessage('CPU行動開始...'); var dx = 0; var dy = 0; var diffX = THIEF.global.adventurer.x - this.x; var diffY = THIEF.global.adventurer.y - this.y; /* var rad = ((Math.atan2(diffY, diffX) * 180.0 / Math.PI) + 360.0) % 360.0; if (typeof rad !== 'number') { } else { if (337.5 < rad || (0 <= rad && rad < 22.5)) { dx = 1; dy = 0; } else if (22.5 <= rad && rad <= 67.5) { dx = 1; dy = 1; } else if (67.5 < rad && rad < 112.5) { dx = 0; dy = 1; } else if (112.5 <= rad && rad <= 157.5) { dx = -1; dy = 1; } else if (157.5 < rad && rad < 202.5) { dx = -1; dy = 0; } else if (202.5 <= rad && rad <= 247.5) { dx = -1; dy = -1; } else if (247.5 < rad && rad < 292.5) { dx = 0; dy = -1; } else if (292.5 <= rad && rad <= 337.5) { dx = 1; dy = -1; } } */ if(diffX > 0){ dx = 1; } else if (diffX < 0){ dx = -1; } if(diffY > 0){ dy = 1; } else if (diffY < 0){ dy = -1; } this.move(dx, dy); THIEF.html.addDebugMessage('...CPU行動完了'); return true; }; THIEF.type.$.move = function(dx, dy) { THIEF.html.addDebugMessage('移動処理 move(' + dx + ', ' + dy + ') を開始...'); THIEF.html.addDebugMessage(THIEF.global.actLV.get(THIEF.E.displayName) + 'のインベントリ座標[' + (this.x + dx) + ', ' + (this.y + dy) + ']を調査を行う。'); var target = THIEF.global.actLV.getInventoryXyLastObject(this.x + dx, this.y + dy); if (this.get(THIEF.E.stackable) || target.get(THIEF.E.stackable)) { var sX = this.x; var sY = this.y; THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + '[' + this.x + ', ' + this.y + ']は' + target.get(THIEF.E.displayName) + '[' + (this.x + dx) + ', ' + (this.y + dy) + ']の上に移動する。'); THIEF.global.actLV.removeFromInventory(this); THIEF.html.addDebugMessage('移動前の座標[' + sX + ', ' + sY + ']の描画を更新'); THIEF.html.refreshXy(sX, sY); this.x = sX + dx; this.y = sY + dy; THIEF.global.actLV.addToInventory(this, this.x, this.y); THIEF.html.addDebugMessage('移動後の座標[' + this.x + ', ' + this.y + ']の描画を更新'); THIEF.html.refreshXy(this.x, this.y); this.ct -= 60; } else { if(target.get(THIEF.E.active)){ THIEF.html.addDebugMessage('active なものが対象なので攻撃してみる。'); target.attackedBy(this); } else { // THIEF.html.addMessage(this.get(THIEF.E.displayName) + 'は移動できない。'); THIEF.html.addDebugMessage( 'インベントリ座標[' + (this.x + dx) + ', ' + (this.y + dy) + '] には移動できない。'); } } THIEF.html.addDebugMessage('...移動処理を完了。'); return true; }; THIEF.type.$.inputWait = function () { this.next = THIEF.type.$.manual; THIEF.html.addDebugMessage('入力待ち'); //THIEF.util.updateStatus(); return false; }; THIEF.type.$.manual = function() { var finish = true; var code = THIEF.global.keycode; if(code !== 0){ THIEF.global.keycode = 0; THIEF.html.addDebugMessage(String.fromCharCode(code) + '(' + code + ')の入力に対する処理を開始...'); if (typeof THIEF.type.$.manual[code] === 'function') { THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + ' の ' + THIEF.type.$.manual[code] + 'を実行'); finish = THIEF.type.$.manual[code].apply(this); } else { finish = false; } if (typeof finish === 'undefined') { finish = false; } THIEF.html.addDebugMessage('...' + String.fromCharCode(code) + '(' + code + ')の入力に対する処理を完了。(return : ' + finish + ')'); if(finish){ this.next = THIEF.type.$.inputWait; } } else { finish = false; THIEF.html.addDebugMessage('無効なキー入力のため、何の処理もしない。') } //THIEF.util.updateStatus(); return finish; }; // 束縛しないように関数化している THIEF.type.$.manual['h'.charCodeAt(0)] = function() { return this.goLeft(); }; THIEF.type.$.manual['k'.charCodeAt(0)] = function() { return this.goUp(); }; THIEF.type.$.manual['j'.charCodeAt(0)] = function() { return this.goDown(); }; THIEF.type.$.manual['l'.charCodeAt(0)] = function() { return this.goRight(); }; THIEF.type.$.manual['y'.charCodeAt(0)] = function() { return this.goUpperLeft(); }; THIEF.type.$.manual['u'.charCodeAt(0)] = function() { return this.goUpperRight(); }; THIEF.type.$.manual['b'.charCodeAt(0)] = function() { return this.goLowerLeft(); }; THIEF.type.$.manual['n'.charCodeAt(0)] = function() { return this.goLowerRight(); }; THIEF.type.$.manual['R'.charCodeAt(0)] = function() { return this.refreshHTML(); }; THIEF.type.$.manual[','.charCodeAt(0)] = function() { return this.pickup(); }; THIEF.type.$.manual['d'.charCodeAt(0)] = function() { return this.drop(); }; /* THIEF.type.$.manual['i'.charCodeAt(0)] = function() { return this.showInventory(); }; */ THIEF.type.$.manual['p'.charCodeAt(0)] = function() { return this.history(); }; THIEF.type.$.manual['s'.charCodeAt(0)] = function() { return this.rest(); }; THIEF.type.$.manual['.'.charCodeAt(0)] = function() { return this.rest(); }; THIEF.type.$.manual['#'.charCodeAt(0)] = function() { return this.extendedCommand(); }; THIEF.type.$.next = function() { return this.cpu(); }; // 基本は CPU THIEF.type.$.notify = function() { if(typeof this.inventory !== "undefined"){ var width = this.get(THIEF.E.inventoryWidth); for(var x=0; x= 100){ if(typeof this[THIEF.E.myOwner][THIEF.E.actObjectList] === "undefined"){ this[THIEF.E.myOwner][THIEF.E.actObjectList] = []; } THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + ' を、オーナ:' + this[THIEF.E.myOwner].get(THIEF.E.displayName) + ' に登録。'); this[THIEF.E.myOwner][THIEF.E.actObjectList].push(this); } }; THIEF.type.$.action = function() { THIEF.html.addDebugMessage(this.get(THIEF.E.displayName) + ' の行動を開始...'); if(typeof this[THIEF.E.actObjectList] !== 'undefined'){ // ct の小さい順にソートする for(var i=0; i=(1+i); j--){ if(this[THIEF.E.actObjectList][j].get(THIEF.E.ct) < this[THIEF.E.actObjectList][j-1].get(THIEF.E.ct)){ var swap = this[THIEF.E.actObjectList][j]; this[THIEF.E.actObjectList][j] = this[THIEF.E.actObjectList][j-1]; this[THIEF.E.actObjectList][j-1] = swap; isSorted = false; } } if(isSorted){ break; } } // ct の大きい順(配列の最後部)から実行 var obj=this[THIEF.E.actObjectList].pop(); for( ; typeof obj !== 'undefined'; obj=this[THIEF.E.actObjectList].pop() ){ THIEF.html.addDebugMessage( obj.get(THIEF.E.displayName) + ' の処理を開始...' ); if(obj.action() === false){ // 行動が完了しない場合、現在のオブジェクトを再登録して一時停止(結果的に入力を待つ) THIEF.html.addDebugMessage('...' + obj.get(THIEF.E.displayName) + ' は処理が完了しなかった。' ); this[THIEF.E.actObjectList].push(obj); break; } THIEF.html.addDebugMessage( '...処理を完了' ); } } var result = true; if(typeof this[THIEF.E.actObjectList] === 'undefined' || this[THIEF.E.actObjectList].length === 0){ if (this.active && this.turnEnd !== THIEF.global.turn) { if(this.get(THIEF.E.ct) >= 100){ if (this.next()) { this.turnEnd = THIEF.global.turn; //this[THIEF.E.ct] -= 100; result = true; } else { result = false; } } } } else if (this[THIEF.E.actObjectList].length > 0) { result = false; } THIEF.html.addDebugMessage('... ' + this.get(THIEF.E.displayName) + ' の行動を完了。 (result = ' + result + ')'); return result; }; THIEF.type.$.decay = function() { //THIEF.html.addMessage(this.name + 'は、腐敗してゆく。(' + this.dp +')'); if (this.decayable) { this.dp--; } if (this.dp <= 0) { //THIEF.html.addMessage(this.name + 'は、腐りきった。'); THIEF.global.actLV.delObject(this); } //this.turnEnd = THIEF.global.turn; return true; }; THIEF.type._life = Object.create(THIEF.type.$); THIEF.type._life.active = true; THIEF.type._life.stackable = false; // on map THIEF.type._life._humanoid = Object.create(THIEF.type._life); THIEF.type._life._humanoid.symbol = 'h'; THIEF.type.Level = Object.create(THIEF.type.$); THIEF.type.Level.getXyObjects = function(x, y) { return this.inventory[x][y]; }; THIEF.type.Level.delObject = function(o) { this.delXyObject(o.x, o.y, o); }; THIEF.type.Level.delXyObject = function(x, y, o) { this.inventory[x][y].remove(o); if (this.mapRefreshPointList) { this.mapRefreshPointList.push({ x: x, y: y }); } }; /* THIEF.type.Level.action = function() { THIEF.global.turn++; for (var i = this.iii; i < this.inventory.length; i++) { for (var j = this.jjj; j < this.inventory[i].length; j++) { for (var k = this.kkk; k < this.inventory[i][j].length; k++) { // 割り込み処理 var finish = this.inventory[i][j][k].action(); if (typeof finish === 'undefined') { alert(this.inventory[i][j][k].next); alert(this.inventory[i][j][k].cpu); } else if (finish === false) { // 処理を中断 this.iii = i; this.jjj = j; this.kkk = k; return; } } } } // map refresh while (this.mapRefreshPointList.length > 0) { var point = this.mapRefreshPointList.pop(); THIEF.html.refreshXy(point.x, point.y); } THIEF.global.turn++; this.iii = 0; this.jjj = 0; this.kkk = 0; if (typeof this.breakCounter === 'undefined') { this.breakCounter = 0; } else if (this.breakCounter < 10) { this.breakCounter++; this.action(); } else { this.breakCounter = 0; alert('bad roop ...?'); } }; */ THIEF.type._item = Object.create(THIEF.type.$); THIEF.type._item.decayable = false; THIEF.type._item.stackable = true; THIEF.type._item.portable = true; // '╳'; // 未登録用印(X に近い) // '░'; // 薄いドット模様 // '░'; // 濃いドット模様 THIEF.type.Floor = Object.create(THIEF.type.$); THIEF.type.Floor.symbol = '╳'; // 未登録用印(X に近い) THIEF.type.Floor.active = false; THIEF.type.Floor.stackable = true; // on map THIEF.type.Floor.Lit = Object.create(THIEF.type.Floor); THIEF.type.Floor.Lit.symbol = '.'; THIEF.type.Floor.Lit.name = { ja : '明るい床', en : 'Lit Floor' }; THIEF.type.Floor.Dark = Object.create(THIEF.type.Floor); THIEF.type.Floor.Dark.symbol = '#'; THIEF.type.Floor.Dark.name = { ja : '暗い床', en : 'Dark Floor' }; THIEF.type.Wall = Object.create(THIEF.type.$); THIEF.type.Wall.symbol = '░'; // 薄いドット模様 THIEF.type.Wall.active = false; THIEF.type.Wall.stackable = false; // on map THIEF.type.Wall.NonDiggable = Object.create(THIEF.type.Wall); THIEF.type.Wall.NonDiggable.symbol = ' '; THIEF.type.Wall.Normal = Object.create(THIEF.type.Wall); THIEF.type.Wall.Normal.symbol = '+'; THIEF.type.Wall.Hidden = Object.create(THIEF.type.Wall); THIEF.type.Wall.Hidden.symbol = ' '; // THIEF.type.WALL.Hidden.symbol = '░' // 薄いドット模様 THIEF.type.Wall.Door = Object.create(THIEF.type.Wall); THIEF.type.Wall.Door.symbol = '+'; THIEF.type.Wall.Door.color = 'burlywood'; /* * Symbol Memo * * ■小文字アルファベットは基本的に 弱い or 普通の強さ……のものが多い * amphibia カエルなどの(小型)両生類 * blob * chiken, cockatrice, (basilisk) 小型の鳥? * dog * eyes, element 球形のもの * felid (cat) * gremlin, gargoyle, goblin, (kobold) 主に敵対的 * humanoid, hobbit, elf, (gnome) 主に友好的 * insect 昆虫。芋虫系は w * j * kop 無能な警官・警備員 * lacertilia, lizard トカゲっぽい小さな生き物。大型のは Reptilia へ。 * mimic * nymph * orc * piercer つらら状生物。 天井から落ちてくる。(それまでは見えない) * quadrupeds 小さい(草食的な)四足獣。大きくて強いのは Q * rat * slime * t * undead (zombi, mummy) * vortex 意思のないエネルギー体 * worm 昆虫は i * x * y * z * * ■大文字アルファベットは普通に強い * Angel * Bard, Bat 大型の飛行生物。猛禽類・ハーピーなど * Centaur -> T * Doragon * Element でかくて強いエレメント。精霊 * Fungus * Golem * HUMANOID (Giant) * Invisible monster * J * K * Lich * Minotaur -> T * Naga -> T * Ogre 鬼。小さい鬼は goblin * Predator 凄まじく猛獣。 * Quadrupeds 大きい(肉食的な)四足獣。小さくて弱いのは q * Reptilia 大型爬虫類。小型は l? * Sea Serpent 海上生物。クラーケンとかもここ。 * Therianthropy 半人半獣 * Unicorn, Uma(笑) * Vampire * Wight, Wraith * X * Y * Z * @ : human, Aventurier and sametype * */ THIEF.type.Human = Object.create(THIEF.type._life._humanoid); THIEF.type.Human.symbol = '@'; /* * & : Daemon */ THIEF.type._life._humanoid.Daemon = Object.create(THIEF.type.Human); THIEF.type._life._humanoid.Daemon.symbol = '&'; THIEF.type._life._humanoid.Daemon.color = '#00FF88'; THIEF.type._life._humanoid.Daemon.name = {ja:'Daemon'}; THIEF.type._life._humanoid.Daemon.hp = 10; /* * * # : dark floor, unbreakable floor * . : lit floor * ~ : tail? -> ̰ ˷ * ^ : trap * ' : * ` : * { : fountain, lake (safe water place) * } : pool, lava (dangerous water place ) * : : Iron Bars (transparent wall) * ; : * - : wall, opened door * | : wall, opened door, tomb * \ : tree -> \ * < : staircase up * > : staircase down * _ : altar, throne, tomb? * * * * * 0(ZERO) : STONE * ? : scrool * ! : potion * " : amulet * + : wall, closed door, edge, book * $ : money * % : food * ( : tool * ) : unknown (oopart) * = : ring * [ : armor * ] : weapon * * : stone, jewel, gem * / : wand * */ THIEF.type._item._food = Object.create(THIEF.type._item); THIEF.type._item._food.symbol = '%'; THIEF.type._item._food.symbolName = { ja : '食料', en : 'Food' }; THIEF.type._item._food._corpse = Object.create(THIEF.type._item._food); THIEF.type._item._food._corpse.decayable = true; THIEF.type._item._food._corpse.next = THIEF.type.$.decay; THIEF.type._item._food._corpse.dp = 20; THIEF.type._item._food.Ration = Object.create(THIEF.type._item._food); THIEF.type._item._food.Ration.name = { ja : 'レーション', en : 'Ration' }; THIEF.type._item._food.Ration.color = 'red'; THIEF.type._item._weapon = Object.create(THIEF.type._item); THIEF.type._item._weapon.symbol = ']'; THIEF.type._item._weapon.symbolName = { ja : '武器', en : 'Weapon' }; THIEF.type._item._weapon.TestDugger = Object.create(THIEF.type._item._weapon); THIEF.type._item._weapon.TestDugger.name = { ja : 'テスト用ダガー', en : 'Dagger(debugging)' }; THIEF.type._item._weapon.TestDugger.color = 'silver';