アルゴリズムゲーム説明書

■目次

概要

敵に攻撃して体力を削るシンプルなゲームです。

ゲーム中に自機を操作する事は出来ません。ゲームが始まれば、勝敗が決まるまで観戦する事になります。
ゲーム中は自機が、あなたが事前に作成した手順(アルゴリズム)に従ってただひたすら動き続けます。

”いかに強いアルゴリズムを作れるか”が試されます。
自信のあるものが出来たら、他の人が作ったアルゴリズムと対戦してみましょう。

更新履歴はこちら。

素材について

無料の音声素材を沢山使わせて頂きました。音声の素材を追加した事によって、個人的にはかなり作品ぽくなった様な気がします。
この様な素晴らしい素材を無料で提供して頂いている事に感謝致します。

ゲームルール

敵を攻撃してHP(体力)を0にすると敵は消滅します。最後まで生き残ったプレイヤーの勝利です。

複数のゲームモードが存在します。

Normal mode

100ターンで強制終了するモードです。

また、制限ターン(100)内に生き残ったプレイヤーが複数居た場合、HPが最も多い者の勝ちです。
同じHPの者が複数居る場合は引き分けです。

制限ターンの半分(50)まで生き残ると、ステージに回復アイテム等が追加投入されます。
今勝ち目が無い場合は50ターンまで逃げ延びるというのも手かもしれません。

Last man standing mode

最後の一人まで永久に戦うモードです。

30ターン毎にアイテムが追加投入されます。

ミサイルアイテムは100ターン毎に順次1個ずつ追加されます。

ユーザーコードの適用

画面右側(或いは下)に、プレイヤーが自機を動かすためのコードを選択するフォームがあります。
Open / Close ボタンでボックスが広がり、ファイル選択フォームが現れます。
ユーザーコードの書かれたファイル( .txt or .js )を選択して 「 適用 」 ボタンを押して下さい。

ユーザーコードのファイルをドラッグ&ドロップで適用させる事も出来ます。
適用させたいキャラクターのプレイヤー情報BOXの上でファイルをドロップして下さい。

ユーザーコードの作り方

作成して頂くコードは大きく分けて2つの機能が有ります。

初期化コード:ゲームの最初の1回だけ実行されるコードです。
メインループのコード:毎ターン実行されるコードです。

例えば、「 変数に初期値を代入しておきたいけど、毎回初期化されるのはマズイ 」 という場合は、その変数の宣言を初期化コードとして記述します。
しかし、「 毎ターン初期化したい 」 という場合は同じ ” 初期化 ” であっても ” メインループ ” のコードとして入力して下さい。
「 前に進む 」 や 「 攻撃する 」 などの毎ターン実行するコードはメインループのコードとして入力して下さい。

※ユーザーコードを外部ファイル化した事で、ユーザーご自身で ”初期化” と ”メインループ” を分けて頂く事になってしまいました。
書式は以下の様になっています。

'use strict';
// 初期化領域
★ここに初期化コードを入れます★

// プレイヤーバージョン
this.playerVer = '★お好きなバージョン番号を★',

// メインループ
this.mainLoop = function () {
★ここにメインループのコードを入れます★
}

この様なコードをテキストファイル( .txt )か、JavaScript ファイル( .js )にして保存してください。

ユーザーコードのサンプルダウンロード

ユーザーコードのサンプルを作成いたしましたので、ご活用下さい。
※下記リンクを右クリックでダウンロードして下さい。

usercode_sample.js

ゲーム内禁止事項

このゲームは素人が Javascript だけで組んだゲームですので、チート(ずる)し放題です。
ルールを守って楽しく遊びましょう。

システム内の変数や関数を直接参照・実行するのは禁止です。

必要な値は常にゲーム独自関数の戻り値より取得して下さい。
動作を知る為にシステム内を覗くのはOKです。

タイマー系の関数は使用禁止です。

setInterval() や setTimeout() などは、案外面白い事になるのかも知れませんが、今の所禁止します。

アイテム紹介

イメージ 名前 説明 備考
回復1

このイメージが表示されているマスに入ると取得できます。

取得すると、HPが最大HPの8割回復します。

 
回復2

このイメージが表示されているマスに入ると取得できます。

HPが最大HPの 2 割回復します。

回復量は少ないですが、回復するタイミングを自由に決める事が出来ます。

 
地雷1

このイメージが表示されているマスに入ると取得できます。

取得する事で始めて使用出来ます。

地雷を踏んだプレイヤーは防御をするしないに関わらず50ポイントのダメージを受けます。
自分で踏んでもダメージはありません。
地雷を設置した場合、地雷の中心部が設置プレイヤーの色に変化します。ただし、敵が設置した地雷の場所を特定する関数はありません。

 
ミサイル1

このイメージが表示されているマスに入ると取得できます。

取得する事で始めて使用出来ます。

命中したプレイヤーは防御をするしないに関わらず90ポイントのダメージを受けます。
さらに、周囲7x7マスの、発射した者を含む全プレイヤーがダメージを受けます。

ダメージは中心の3x3マスが90。
その外の5x5マスでは60。
その外の7x7マスでは30となります。

ミサイルを発射した者を含めて全員退場となった場合は、「 ~ の自滅 」 とコールされます。

※全プレイヤーの番手で前進するという性質上、プレイヤー数が多い程1ターンに前進する距離が多くなります(速くなる)。

 

ゲーム独自関数

移動系

関数 説明 使用例 備考
playerMove() 1マス前進します。
1ターン1回のみ使用可能です。
   
playerDirection(Dir) プレイヤーの向きを変えます。
引数に下記数値を与えて方向を決めます。
1:左, 2:上, 3:右, 4:下

右に向きを変える時

playerDirection(3);

 

攻撃・守備系

関数 説明 使用例 備考
playerAttack() 攻撃します。   攻撃・防御は1ターン内にどちらか1回のみ使用可能です。
つまり、攻撃を選択すれば防御が外れます。逆も同様です。
playerDefence() 防御します。
攻撃を受けた時のHPの減りが1/2になります。
 
playerUseHeal2() 回復2を使用します。

 

 
playerPutMine() 地雷を設置します。

 

 
playerLaunchSissile() ミサイルを発射します。

 

 

情報系

※各プレイヤーと一意の関係にあるのは「プレイヤーナンバー と ID」です。

ゲームの情報を得る

関数 説明 使用例 備考
playerGetTurn() 現在のターン数を取得します。

現在のターン数を取得したい時、以下のコードで hoge に現在のターン数が代入されます。

hoge = playerGetTurn();

 
playerGetStageInfo()

ステージの情報を取得します。
情報は連想配列で、以下のキーで情報を取り出せます。

maxX : 横マスの最大値
maxY : 縦マスの最大値

※ステージの左上が原点で、マスの値は 0 です。

ステージの横マスの最大値を知りたい時。

myStageInfo = playerGetStageInfo();
writeLog(myStageInfo['maxX']); // ログに横マスの最大値が表示される

 

自機・敵機の情報を得る

関数 説明 使用例 備考
playerGetInfoObj(WhoIs)

自機・敵の様々な情報を取得出来ます。
引数に以下の文字列を入力して情報を指定します。

プレイヤーナンバー : 敵の情報を得る場合 (数値)
me : 自機の情報を得る場合(英小文字)

情報は連想配列として返されます。
連想配列からは、以下のキー値で情報を取得できます。

No:プレイヤーナンバー
id:プレイヤーID
HP:体力
maxHP:体力最大値
attack:攻撃力
defence:防御力
direction:方向
positionX:X座標
positionY:Y座標
heal2 : 回復2の個数
mine:所持地雷の個数(自機の情報の時のみ)
missile:所持ミサイルの弾数
out:生死(0:生、1:死)

自機のHP(体力)が知りたい時、以下の式で各 fuga... に値が代入されます。

hoge = playerGetInfoObj('me');
fugaHP = hoge['HP']; // 自機の体力
fugaX = hoge['positionX']; // 自機のx座標
fugaY = hoge['positionY']; // 自機のy座標

敵の1番目の情報が知りたい場合は以下の様にします。

hoge = playerGetInfoObj(playerGetLiveEnemy()[0]);
fugaHP = hoge['HP']; // 自機の体力
fugaX = hoge['positionX']; // 自機のx座標
fugaY = hoge['positionY']; // 自機のy座標

※playerGetInfoObj(WhoIs) で得られる情報は取得した時点のものです。
最新の情報を得たい場合は値を使用する直前に取得する必要があります。

プレイヤーを確実に特定出来るのはプレイヤーナンバーとIDです。

自機の情報を得る

関数 説明 使用例 備考
playerGetInfo(Info)

自機の様々な情報を取得出来ます。

引数に以下の文字列を入力して情報を指定します。

NO:プレイヤーナンバー
ID:プレイヤーID
HP:体力
MAXHP:体力最大値
ATTACK:攻撃力
DEFENCE:防御力
DIRECTION:方向
X:X座標
Y:Y座標
MINE:所持地雷の個数
MISSILE:所持ミサイルの弾数
(全て英大文字)

自機のHP(体力)が知りたい時、以下の式で hoge に体力値が代入されます。

hoge = playerGetInfo("HP");

プレイヤーを確実に特定出来るのはプレイヤーナンバーとIDです。
playerGetPosition(Axis)

自機の座標位置を返します。
引数に下記文字列を入力すると、それぞれの座標を知る事が出来ます。

X:X座標, Y:Y座標 (それぞれ英大文字)

自機のX座標が知りたい時。
以下の式で変数 hoge にX座標が代入されます。

hoge = playerGetPosition("X");

※マップは左上が ( 0,0 ) です。
playerGetDirection()

自機の方向を返します。
戻り値は以下の数値で返されます。

1:左, 2:上, 3:右, 4:下

自機の向きが知りたい時。
以下の式で変数 hoge に向きが代入されます。

hoge = playerGetDirection();

 

敵機の情報を得る

関数 説明 使用例 備考
playerGetLiveEnemy() 生存している敵のプレイヤーナンバーを取得します。
戻り値は配列として返されます。
   
playerGetEnemyInfo(No,Info)

敵の様々な情報を取得出来ます。

第2引数に文字列を入力して情報を指定します。

第1引数:敵のプレイヤーナンバー(数値)

第2引数:情報の種類(英大文字)
NO:プレイヤーナンバー
ID:プレイヤーID
HP:体力
MAXHP:体力最大値
ATTACK:攻撃力
DEFENCE:防御力
DIRECTION:方向
X:X座標
Y:Y座標
HEAL2:回復2個数
OUT:生死(0:生、1:死)

1番目の敵のHP(体力)が知りたい時、以下の式で hoge に体力値が代入されます。

hoge = playerGetEnemyInfo(1,"HP");

プレイヤーを確実に特定出来るのはプレイヤーナンバーとIDです。
playerGetNearList(select)

自機から近い順に、アイテム・敵の座標をリストアップします。
引数に以下の文字列を入力して情報を指定します。
なお敵のリストには、消滅した敵は含まれません。

HealItem : 回復アイテム( 1,2全て )
HealItem1 : 回復1アイテム
HealItem2 : 回復2アイテム
MineItem : 地雷アイテム
MissileItem : ミサイルアイテム
Player : 敵

取得されたリストは配列で、以下の様な形式です。
[
 {
  'no' : プレイヤーナンバー,
  'x' : x座標,
  'y' : y座標
 } ,
 .....
]

アイテムの場合は以下の様な配列です。
[
 {
  'x' : x座標,
  'y' : y座標
 } ,
 .....
]

自機から最も近い敵の座標を取得したい場合、以下のコードで EnemyNo, EnemyX, EnemyY それぞれにプレイヤーナンバー、 x座標、y座標が取得されます。

hoge = playerGetNearList('Player');
var EnemyNo= hoge[0]['no'];
var EnemyX = hoge[0]['x'];
var EnemyY = hoge[0]['y'];

 
playerGetAroundEnemy()

自機の上下左右1マスに敵が居るかどうかを判定します。
戻り値は5つの値の配列です。

戻り値の意味
[ 総評, 左に居るか, 上に居るか, 右に居るか, 下に居るか ]

全て true か false で表されます。
”総評” は、上下左右1つでも敵が居れば true。全く居なければ false となります。

上下左右に敵が居るか知りたい時、以下のコードで hoge に情報が代入されます。

hoge = playerGetAroundEnemy();

 

アイテムの情報を得る

関数 説明 使用例 備考
playerGetHealItemList()

ステージ上の回復アイテムのリストを取得できます。
データは配列で渡されます。取得できる内容は以下の通りです。

type : 回復アイテムの種類
positionX : x座標
positionY : y座標

回復アイテムの3個目の座標を知りたい場合。

hoge = playerGetHealItemList();
var myHealItemX = hoge[2]['positionX'];
var myHealItemY = hoge[2]['positionY'];

 
playerGetMineItemList()

ステージ上の地雷アイテムのリストを取得できます。
データは配列で渡されます。取得できる内容は以下の通りです。

type : 地雷アイテムの種類
positionX : x座標
positionY : y座標

地雷アイテムの1個目の座標を知りたい場合。

hoge = playerGetMineItemList();
var myMineItemX = hoge[0]['positionX'];
var myMineItemY = hoge[0]['positionY'];

 
playerGetMissileItemList()

ステージ上のミサイルアイテムのリストを取得できます。
データは配列で渡されます。取得できる内容は以下の通りです。

type : ミサイルアイテムの種類
positionX : x座標
positionY : y座標

ミサイルアイテムの1個目の座標を知りたい場合。

hoge = playerGetMineItemList();
var myMissileItemX = hoge[0]['positionX'];
var myMissileItemY = hoge[0]['positionY'];

 

その他

関数 説明 使用例 備考
writeLog(Text) ログにテキストを出力します。
引数に任意の文字列、或いは変数などを入力すると、ログ(HPゲージ下)に文字列、或いは変数の内容などが出力されます。
デバッグなどに活用して下さい。

自機のX座標をログに出力したい時。

writeLog(playerGetPosition("X"));

 

ゲームの進め方のヒント

敵プレイヤーの情報を得るにはプレイヤーNoが必要です

プレイヤーにはそれぞれゲーム開始時にプレイヤーNoがランダムに割り振られます。
プレイヤーNoは「ゲームスタート」ボタンを押す度にランダムに再配布されますので、事前に知る事は出来ません。

プレイヤーNoを取得する方法は
playerGetLiveEnemy()
playerGetNearList(select)
等の関数を使う事です。

これらの関数で得られたプレイヤーNoを
playerGetEnemyInfo(No,Info)
等の関数に引数として渡す事で、敵プレイヤーの様々な情報が得られます。

配列・連想配列とは

関数の説明で「情報は連想配列として返されます」等の表記があります。

配列について

配列とは以下の様に定義されているものです。

var myArray = ['a','b','c'];

変数の中に変数が3つ入っている様な感じです。
この配列 myArray から「a」を取り出したい場合は次の様に記述します。

var hoge = myArray[0];

myArray の 0 番目という意味です。
これで hoge に 「a」という文字が代入されます。

連想配列について

連想配列とは以下の様に定義されているものです。

var myArray = { 名前: 'Taka', 相棒: 'Toshi', 職業: '芸人' };

配列の値に名前が付いた様な感じです。

この連想配列 myArray から「芸人」を取り出したい場合は次の様に記述します。

var hoge = myArray['職業'];

「名前」や「職業」 の文字を ” キー値 ” と 呼びます。
「職業」は文字列なので ’ で囲むことを忘れないで下さい。
また、myArray[2] の様な値の取り出し方は出来ません。

その他

このゲームの性質として「先手不利」というハンデが発生してしまいます。
例えば攻撃する相手を選択するために playerGetLiveEnemy() を使うと、0番目から順に記載されたリストが返されます。そして特に考えが無ければ0番目の座標を取得して自機を攻撃に向かわせるでしょう。これを複数人が行ったとすると、当然0番目がリンチ状態になります。

これを出来るだけ公平にする為、ゲームスタート毎にプレイヤーの動作順をランダムに変更しています。
ただ、ランダムにするだけでは不利な状況は避けられないので、出来れば10回以上対戦を行ってより多くの勝利を収めたプレイヤーの勝ちという風にした方が良いと思います。