/*
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 += '
| 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('(')) + ' | |
| # | '; } 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