Playable game, only end of game isn't handled yet
This commit is contained in:
parent
4cd6842c01
commit
dc49f4eb0e
7 changed files with 248 additions and 48 deletions
|
@ -35,7 +35,7 @@ executable hanafudapi
|
|||
build-depends: base >=4.10 && <4.11
|
||||
, bytestring
|
||||
, containers
|
||||
, hanafuda >= 0.2.1
|
||||
, hanafuda >= 0.3.0
|
||||
, http-types
|
||||
, aeson
|
||||
, mtl
|
||||
|
|
|
@ -5,7 +5,8 @@ function Fun() {
|
|||
map: map,
|
||||
mapFilter: mapFilter,
|
||||
isSet: isSet,
|
||||
of: of
|
||||
of: of,
|
||||
proj: proj
|
||||
};
|
||||
|
||||
function insert(obj, t, compare, min, max) {
|
||||
|
@ -44,6 +45,10 @@ function Fun() {
|
|||
return function(key) {return o[key];};
|
||||
}
|
||||
|
||||
function proj(key) {
|
||||
return function(o) {return o[key];};
|
||||
}
|
||||
|
||||
function mapFilter(mapper, predicate) {
|
||||
return function(array) {
|
||||
return array.reduce(function(accumulator, elem) {
|
||||
|
|
35
www/game.css
35
www/game.css
|
@ -2,17 +2,27 @@
|
|||
clear: both;
|
||||
}
|
||||
|
||||
li.card {
|
||||
#game ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#game .card {
|
||||
background: #fff;
|
||||
display: inline-block;
|
||||
border-radius: 0.5em;
|
||||
border: 1px solid #555;
|
||||
width: 6em;
|
||||
height: 10em;
|
||||
width: 5em;
|
||||
height: 8em;
|
||||
max-height: 10%;
|
||||
float: left;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
#river li.card.candidate, #hand li.card {
|
||||
#turned.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#river li.card.candidate, #hand.yourTurn li.card {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -23,3 +33,20 @@ li.card {
|
|||
#hand li.card.selected {
|
||||
margin-top: -1em;
|
||||
}
|
||||
|
||||
#opponent, #own {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#opponent {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#own {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#opponent .card, #own .card {
|
||||
margin-left: -2em;
|
||||
}
|
||||
|
|
138
www/game.js
138
www/game.js
|
@ -1,26 +1,52 @@
|
|||
function Game(modules) {
|
||||
var turned = document.getElementById('turned');
|
||||
var status = {
|
||||
dom: document.getElementById('status'),
|
||||
playing: false,
|
||||
step: null,
|
||||
month: null
|
||||
};
|
||||
var sets = {
|
||||
river : cardSet('river'),
|
||||
hand : cardSet('hand'),
|
||||
river: cardSet('river'),
|
||||
hand: cardSet('hand'),
|
||||
};
|
||||
var selected = null;
|
||||
|
||||
modules.messaging.addEventListener(["NewGame"], function(o) {
|
||||
o.game.river.forEach(function(cardName) {
|
||||
var card = new RiverCard(cardName);
|
||||
sets.river.card[card.value] = card;
|
||||
sets.river.dom.appendChild(card.dom);
|
||||
});
|
||||
o.game.players[modules.session.getKey()].hand.forEach(function(cardName) {
|
||||
var card = new HandCard(cardName);
|
||||
sets.hand.card[card.value] = card;
|
||||
sets.hand.dom.appendChild(card.dom);
|
||||
});
|
||||
modules.messaging.addEventListener(["Game"], function(o) {
|
||||
status.step = o.game.step.tag;
|
||||
setStatus(o.game);
|
||||
setCaptures(o.game);
|
||||
[
|
||||
{name: 'river', cards: o.game.river},
|
||||
{name: 'hand', cards: o.game.players[modules.session.getKey()].hand}
|
||||
].forEach(setCardSet);
|
||||
if(status.step == "Turned") {
|
||||
turned.textContent = o.game.step.contents;
|
||||
turned.classList.remove("hidden");
|
||||
if(status.playing) {
|
||||
selected = o.game.step.contents;
|
||||
showCandidates(modules.hanafuda.Card[selected], true);
|
||||
}
|
||||
} else {
|
||||
turned.classList.add("hidden");
|
||||
}
|
||||
if(status.playing && status.step == "Scored") {
|
||||
play({koiKoi: confirm(
|
||||
"You scored ! Do you want to go on ? Press cancel to just get your points and end current month"
|
||||
)});
|
||||
}
|
||||
});
|
||||
|
||||
function play(move) {
|
||||
modules.messaging.send({
|
||||
tag: "Play",
|
||||
move: move
|
||||
});
|
||||
}
|
||||
|
||||
function cardSet(id) {
|
||||
return {
|
||||
card: {},
|
||||
card: null,
|
||||
dom: document.getElementById(id)
|
||||
};
|
||||
}
|
||||
|
@ -29,7 +55,53 @@ function Game(modules) {
|
|||
return modules.fun.mapFilter(
|
||||
modules.fun.of(sets.river.card),
|
||||
modules.fun.isSet
|
||||
)(modules.hanafuda.sameMonth(card));
|
||||
)(modules.hanafuda.sameMonth(card).map(modules.fun.proj('name')));
|
||||
}
|
||||
|
||||
function setStatus(game) {
|
||||
modules.dom.clear(status.dom);
|
||||
status.month = game.month;
|
||||
var month = document.createElement('li');
|
||||
month.textContent = "This month's flower is the " + status.month;
|
||||
status.dom.appendChild(month);
|
||||
var playing = document.createElement('li');
|
||||
status.playing = modules.session.is(game.playing);
|
||||
if(status.playing) {
|
||||
sets.hand.dom.classList.toggle("yourTurn", status.step == "ToPlay");
|
||||
playing.textContent = "Your turn";
|
||||
} else {
|
||||
sets.hand.dom.classList.remove("yourTurn");
|
||||
playing.textContent = modules.room.name(game.playing) + " is playing";
|
||||
}
|
||||
status.dom.appendChild(playing);
|
||||
}
|
||||
|
||||
function setCaptures(game) {
|
||||
for(var key in game.players) {
|
||||
var elem = document.getElementById(modules.session.is(key) ? "own" : "opponent");
|
||||
elem.getElementsByClassName('score')[0].textContent = game.scores[key] + " pts";
|
||||
Array.prototype.forEach.call(elem.getElementsByTagName('ul'), modules.dom.clear);
|
||||
game.players[key].meld.forEach(function(cardName) {
|
||||
var card = new Card(cardName);
|
||||
elem.getElementsByClassName(card.value.family.class)[0].appendChild(card.dom);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setCardSet(conf) {
|
||||
var set = sets[conf.name];
|
||||
var constructor = conf.name == "river" ? RiverCard : HandCard;
|
||||
modules.dom.clear(set.dom);
|
||||
set.card = {};
|
||||
conf.cards.forEach(function(cardName) {
|
||||
var card = new constructor(cardName);
|
||||
set.card[cardName] = card;
|
||||
set.dom.appendChild(card.dom);
|
||||
});
|
||||
}
|
||||
|
||||
function showCandidates(card, yes) {
|
||||
matchingInRiver(card).forEach(function(riverCard) {riverCard.setCandidate(yes);});
|
||||
}
|
||||
|
||||
function Card(name) {
|
||||
|
@ -52,10 +124,11 @@ function Game(modules) {
|
|||
var card = this;
|
||||
return function() {
|
||||
if(card.candidate) {
|
||||
modules.messaging.send({
|
||||
tag: "Play",
|
||||
move: {capture: [sets.hand.card[selected].name, card.name]}
|
||||
});
|
||||
var withCard = selected;
|
||||
selected = null;
|
||||
play(
|
||||
status.step == 'ToPlay' ? {capture: [withCard, card.name]} : {choose: card.name}
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -70,20 +143,24 @@ function Game(modules) {
|
|||
}
|
||||
|
||||
HandCard.prototype.onClick = function() {
|
||||
var card = this;
|
||||
return function() {
|
||||
if(selected != undefined) {
|
||||
sets.hand.card[selected].setSelected(false);
|
||||
} else {
|
||||
card.play();
|
||||
}
|
||||
};
|
||||
if(status.playing && status.step == "ToPlay") {
|
||||
var card = this;
|
||||
return function() {
|
||||
if(selected != undefined) {
|
||||
sets.hand.card[selected].setSelected(false);
|
||||
} else {
|
||||
card.play();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return function() {};
|
||||
}
|
||||
};
|
||||
|
||||
HandCard.prototype.setSelected = function(yes) {
|
||||
selected = yes ? this.value : null;
|
||||
selected = yes ? this.name : null;
|
||||
this.dom.classList.toggle('selected', yes);
|
||||
matchingInRiver(this.value).forEach(function(card) {card.setCandidate(yes);});
|
||||
showCandidates(this.value, yes);
|
||||
}
|
||||
|
||||
HandCard.prototype.play = function() {
|
||||
|
@ -91,8 +168,7 @@ function Game(modules) {
|
|||
if(matching.length > 1) {
|
||||
this.setSelected(true);
|
||||
} else {
|
||||
modules.messaging.send({tag: "Play", move: {play: this.name}})
|
||||
play({play: this.name});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
function Hanafuda() {
|
||||
function Hanafuda(modules) {
|
||||
var Flower = Object.freeze({
|
||||
Pine: 0,
|
||||
Plum: 1,
|
||||
|
@ -13,7 +13,54 @@ function Hanafuda() {
|
|||
Willow: 10,
|
||||
Paulownia: 11
|
||||
});
|
||||
var Card = Object.freeze({
|
||||
|
||||
var Family = Object.freeze(
|
||||
["Kasu", "Tan", "Tane", "Hikari"].reduce(function(o, name) {
|
||||
o[name] = {class: name[0].toLowerCase() + name.slice(1)};
|
||||
return o;
|
||||
}, {})
|
||||
);
|
||||
|
||||
var CardNames = [
|
||||
"Pine0", "Pine1", "PinePoetry", "Crane",
|
||||
"Plum0", "Plum1", "PlumPoetry", "BushWarbler",
|
||||
"Cherry0", "Cherry1", "CherryPoetry", "CampCurtain",
|
||||
"Wisteria0", "Wisteria1", "WisteriaRed", "Cuckoo",
|
||||
"Iris0", "Iris1", "IrisRed", "EightPlankBridge",
|
||||
"Peony0", "Peony1", "PeonyBlue", "Butterflies",
|
||||
"BushClover0", "BushClover1", "BushCloverRed", "Boar",
|
||||
"SusukiGrass0", "SusukiGrass1", "Geese", "FullMoon",
|
||||
"Chrysanthemum0", "Chrysanthemum1", "ChrysanthemumBlue", "SakeCup",
|
||||
"Maple0", "Maple1", "MapleBlue", "Deer",
|
||||
"Lightning", "WillowRed", "Swallow", "RainMan",
|
||||
"Paulownia0", "Paulownia1", "Sand", "Phoenix"
|
||||
];
|
||||
|
||||
var Card = Object.freeze(
|
||||
CardNames.reduce(function(o, name, i) {
|
||||
o[name] = {
|
||||
id: i,
|
||||
family: findFamily(name, i),
|
||||
flower: Math.floor(i / 4),
|
||||
name: name
|
||||
};
|
||||
return o;
|
||||
}, {})
|
||||
);
|
||||
|
||||
function findFamily(name, i) {
|
||||
if((i % 4 < 2 && i < 41) || (i > 43 && i < 47)) {
|
||||
return Family.Kasu;
|
||||
} else if(name.match(/(Blue|Poetry|Red)/)) {
|
||||
return Family.Tan;
|
||||
} else if(["Crane", "CampCurtain", "FullMoon", "RainMan", "Phoenix"].includes(name)) {
|
||||
return Family.Hikari;
|
||||
} else {
|
||||
return Family.Tane;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Pine0: 0, Pine1: 1, PinePoetry: 2, Crane: 3,
|
||||
Plum0: 4, Plum1: 5, PlumPoetry: 6, BushWarbler: 7,
|
||||
Cherry0: 8, Cherry1: 9, CherryPoetry: 10, CampCurtain: 11,
|
||||
|
@ -28,20 +75,49 @@ function Hanafuda() {
|
|||
Paulownia0: 44, Paulownia1: 45, Sand: 46, Phoenix: 47
|
||||
});
|
||||
|
||||
var kasu = Object.freeze(
|
||||
Array.apply(null, Array(10)).reduce(
|
||||
function(t, _, i) {return t.concat(4*i, 4*i + 1);}, []
|
||||
).concat(
|
||||
["Lightning", "Paulownia0", "Paulownia1", "Sand"].map(modules.fun.of(Card))
|
||||
).reduce(setKey, {})
|
||||
);
|
||||
|
||||
var tan = Object.freeze(
|
||||
["Pine", "Plum", "Cherry"].map(function(name) {return name+"Poetry";}).concat(
|
||||
["Wisteria", "Iris", "BushClover"].map(function(name) {return name+"Red";}),
|
||||
["Peony", "Chrysanthemum", "Maple"].map(function(name) {return name+"Blue";})
|
||||
)
|
||||
.map(modules.fun.of(Card))
|
||||
.reduce(setKey, {})
|
||||
);
|
||||
|
||||
var tane = Object.freeze(
|
||||
[
|
||||
"BushWarbler", "Cuckoo", "EightPlankBridge", "Butterflies",
|
||||
"Boar", "Geese", "SakeCup", "Deer", "Swallow"
|
||||
]
|
||||
.map(modules.fun.of(Card))
|
||||
.reduce(setKey, {})
|
||||
);
|
||||
|
||||
var light = Object.freeze(
|
||||
["Crane", "CampCurtain", "FullMoon", "RainMan", "Phoenix"]
|
||||
.map(modules.fun.of(Card))
|
||||
.reduce(setKey, {})
|
||||
);
|
||||
*/
|
||||
|
||||
return {
|
||||
Flower: Flower,
|
||||
Family: Family,
|
||||
Card: Card,
|
||||
flower: flower,
|
||||
sameMonth: sameMonth
|
||||
};
|
||||
|
||||
function flower(card) {
|
||||
return Math.floor(card / 4);
|
||||
}
|
||||
|
||||
function sameMonth(card) {
|
||||
var first = 4 * flower(card);
|
||||
return [0,1,2,3].map(function(i) {return first + i;});
|
||||
var first = 4 * card.flower;
|
||||
return [0,1,2,3].map(function(i) {return Card[CardNames[first + i]];});
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -36,10 +36,26 @@
|
|||
</form>
|
||||
</div>
|
||||
<div id="game">
|
||||
<ul id="status"></ul>
|
||||
<h2>River</h2>
|
||||
<ul id="river"></ul>
|
||||
<span id="turned" class="card hidden"></span>
|
||||
<h2>Hand</h2>
|
||||
<ul id="hand"></ul>
|
||||
<div id="opponent">
|
||||
<span class="score"></span>
|
||||
<ul class="kasu"></ul>
|
||||
<ul class="tane"></ul>
|
||||
<ul class="tan"></ul>
|
||||
<ul class="hikari"></ul>
|
||||
</div>
|
||||
<div id="own">
|
||||
<span class="score"></span>
|
||||
<ul class="kasu"></ul>
|
||||
<ul class="tane"></ul>
|
||||
<ul class="tan"></ul>
|
||||
<ul class="hikari"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<p id="debug"></p>
|
||||
</body>
|
||||
|
|
|
@ -6,8 +6,8 @@ window.addEventListener('load', function() {
|
|||
var session = Session({messaging: messaging});
|
||||
var room = Room({dom: dom, messaging: messaging, session: session, fun: fun});
|
||||
var login = Login({dom: dom, messaging: messaging, room: room, screen: screen, session: session});
|
||||
var hanafuda = Hanafuda();
|
||||
var game = Game({dom: dom, fun: fun, hanafuda: hanafuda, messaging: messaging, session: session});
|
||||
var hanafuda = Hanafuda({fun: fun});
|
||||
var game = Game({dom: dom, fun: fun, hanafuda: hanafuda, messaging: messaging, room: room, session: session});
|
||||
|
||||
messaging.start();
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue