シェフィを実装しようと思い立った俺達は基本ルールの実装を何とか終えたばかり。しかしUIが付いてないので肝心のゲームができない状態。果たして無事にゲームを実装し終えることができるのか。
今の段階では実装したゲームがちゃんと動くことさえ確認できれば十分なので、
当初の予定通り、
仮UIはテキストで盤面を表示し、
選択肢はボタンの形で提示することにします。
まずは盤面と選択肢と補助メッセージを表示できるようざっくりとページ index.html
を書きましょう:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Shephy JS</title>
<link href="app.css" rel="stylesheet">
</head>
<body>
<div id="world">
<div id="sheepStock">
<div id="sheepStock1">1 (<span class="count"></span>)</div>
<div id="sheepStock3">3 (<span class="count"></span>)</div>
<div id="sheepStock10">10 (<span class="count"></span>)</div>
<div id="sheepStock30">30 (<span class="count"></span>)</div>
<div id="sheepStock100">100 (<span class="count"></span>)</div>
<div id="sheepStock300">300 (<span class="count"></span>)</div>
<div id="sheepStock1000">1000 (<span class="count"></span>)</div>
</div>
<div id="enemySheepCount">Enemy: <span class="count"></span></div>
<div id="field">Field: <span class="cards"></span></div>
<div id="hand">Hand: <span class="cards"></span></div>
<div id="deck">Deck: <span class="count"></span></div>
<div id="discardPile">Discard pile: <span class="cards"></span></div>
<div id="exile">Exile: <span class="cards"></span></div>
</div>
<div id="console">
<div id="message"></div>
<div id="moves"></div>
</div>
<script src="jquery.js"></script>
<script src="app.js"></script>
</body>
</html>
今の段階で外観はどうでも良いのでCSS app.css
は空で構いません:
// TODO: 本格的なUIを作る時に考える。
app.js
には今まで実装してきたコードが一通り入っているものとします(全体像は省略)。
jquery.js
は適当に最新版をコピーしておきましょう(執筆時点だと2.1.1)。
現在の局面(盤面+選択肢)を表示する drawGameTree
を定義しましょう。
テキストで表示するだけなので楽勝ですね:
function drawGameTree(gameTree) {
var w = gameTree.world;
S.RANKS.forEach(function (rank) {
$('#sheepStock' + rank + ' > .count').text(w.sheepStock[rank].length);
});
$('#enemySheepCount > .count').text(w.enemySheepCount);
$('#field > .cards').text(
w.field
.map(function (c) {return c.rank;})
.join(', ')
);
$('#hand > .cards').text(textizeCards(w.hand));
$('#deck > .count').text(w.deck.length);
$('#discardPile > .cards').text(textizeCards(w.discardPile));
$('#exile > .cards').text(textizeCards(w.exile));
$('#message').text(
gameTree.moves.length == 0
? S.judgeGame(gameTree.world).description
: 'Choose a move:'
);
$('#moves').empty().append(gameTree.moves.map(nodizeMove));
}
手札や捨て場等、カードの集合を表示する箇所については名前を列挙するだけにします:
function textizeCards(cs) {
if (cs.length == 0)
return '-';
else
return cs.map(function (c) {return c.name;}).join(', ');
}
勝敗を判定して適切なメッセージを表示する関数も用意しましょう
(よくよく考えるとこれはlistPossibleMovesForBasicRules
と若干被ってる部分があるので要改善ですね。
後で考えることにします):
S.judgeGame = function (world) {
if (world.field.some(function (c) {return c.rank == 1000;})) {
return {
result: 'win',
description: 'You win!'
};
}
if (world.enemySheepCount == 1000) {
return {
result: 'lose',
description: 'Enemies reached 1000 sheep - you lose.'
};
}
if (world.field.length == 0) {
return {
result: 'lose',
description: 'You lost all your sheep - you lose.'
};
}
throw 'Invalid operation';
};
後は選択肢をボタンとして提示する部分を作れば完成です:
function nodizeMove(m) {
var $m = $('<input>');
$m.attr({
type: 'button',
value: m.description
});
$m.click(function () {
drawGameTree(S.force(m.gameTreePromise));
});
return $m;
}
これでルールエンジンと仮UIはできたものの、
肝心のゲームを始める部分ができていませんでした。
と言う訳でさくっと作りましょう。
初期盤面からゲーム木を作ってそれを表示するだけなので簡単ですね:
$(function () {
drawGameTree(S.makeGameTree(S.makeInitalWorld()));
});
と言う訳で実際に遊んでみましょう!
やはりしょぼいですね……とはいえモノは動いているので良しとしましょう。
これで一応ゲームは遊べるようになったものの、
個々のカードを全く実装していないので、
これでは何も楽しくありません。
と言う訳で次回はイベントカード実装編です。