mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-05 00:54:52 +01:00
wip
This commit is contained in:
parent
161fd4afab
commit
0bca0e8a02
7 changed files with 124 additions and 56 deletions
|
@ -475,8 +475,8 @@ class OthelloContext extends Context {
|
||||||
othelloAi('white', this.othello);
|
othelloAi('white', this.othello);
|
||||||
if (this.othello.getPattern('black').length === 0) {
|
if (this.othello.getPattern('black').length === 0) {
|
||||||
this.bot.clearContext();
|
this.bot.clearContext();
|
||||||
const blackCount = this.othello.board.map(row => row.filter(s => s == 'black').length).reduce((a, b) => a + b);
|
const blackCount = this.othello.board.filter(s => s == 'black').length;
|
||||||
const whiteCount = this.othello.board.map(row => row.filter(s => s == 'white').length).reduce((a, b) => a + b);
|
const whiteCount = this.othello.board.filter(s => s == 'white').length;
|
||||||
const winner = blackCount == whiteCount ? '引き分け' : blackCount > whiteCount ? '黒の勝ち' : '白の勝ち';
|
const winner = blackCount == whiteCount ? '引き分け' : blackCount > whiteCount ? '黒の勝ち' : '白の勝ち';
|
||||||
return this.othello.toString() + `\n\n~終了~\n\n黒${blackCount}、白${whiteCount}で${winner}です。`;
|
return this.othello.toString() + `\n\n~終了~\n\n黒${blackCount}、白${whiteCount}で${winner}です。`;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import Game, { pack } from '../../models/othello-game';
|
||||||
|
|
||||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||||
// Get 'my' parameter
|
// Get 'my' parameter
|
||||||
const [my = false, myErr] = $(params.my).boolean().$;
|
const [my = false, myErr] = $(params.my).optional.boolean().$;
|
||||||
if (myErr) return rej('invalid my param');
|
if (myErr) return rej('invalid my param');
|
||||||
|
|
||||||
const q = my ? {
|
const q = my ? {
|
||||||
|
|
|
@ -34,6 +34,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||||
black_user_id: parentIsBlack ? exist.parent_id : user._id,
|
black_user_id: parentIsBlack ? exist.parent_id : user._id,
|
||||||
white_user_id: parentIsBlack ? user._id : exist.parent_id,
|
white_user_id: parentIsBlack ? user._id : exist.parent_id,
|
||||||
turn_user_id: parentIsBlack ? exist.parent_id : user._id,
|
turn_user_id: parentIsBlack ? exist.parent_id : user._id,
|
||||||
|
is_ended: false,
|
||||||
logs: []
|
logs: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@ export interface IGame {
|
||||||
created_at: Date;
|
created_at: Date;
|
||||||
black_user_id: mongo.ObjectID;
|
black_user_id: mongo.ObjectID;
|
||||||
white_user_id: mongo.ObjectID;
|
white_user_id: mongo.ObjectID;
|
||||||
|
turn_user_id: mongo.ObjectID;
|
||||||
|
is_ended: boolean;
|
||||||
|
winner_id: mongo.ObjectID;
|
||||||
logs: any[];
|
logs: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +43,7 @@ export const pack = (
|
||||||
// Populate user
|
// Populate user
|
||||||
_game.black_user = await packUser(_game.black_user_id, meId);
|
_game.black_user = await packUser(_game.black_user_id, meId);
|
||||||
_game.white_user = await packUser(_game.white_user_id, meId);
|
_game.white_user = await packUser(_game.white_user_id, meId);
|
||||||
|
_game.winner = await packUser(_game.winner_id, meId);
|
||||||
|
|
||||||
resolve(_game);
|
resolve(_game);
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,51 +19,68 @@ export default function(request: websocket.request, connection: websocket.connec
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case 'set':
|
case 'set':
|
||||||
if (msg.pos == null) return;
|
if (msg.pos == null) return;
|
||||||
const pos = msg.pos;
|
set(msg.pos);
|
||||||
|
|
||||||
const game = await Game.findOne({ _id: gameId });
|
|
||||||
|
|
||||||
const o = new Othello();
|
|
||||||
|
|
||||||
game.logs.forEach(log => {
|
|
||||||
o.set(log.color, log.pos);
|
|
||||||
});
|
|
||||||
|
|
||||||
const myColor = game.black_user_id.equals(user._id) ? 'black' : 'white';
|
|
||||||
const opColor = myColor == 'black' ? 'white' : 'black';
|
|
||||||
|
|
||||||
if (!o.canReverse(myColor, pos)) return;
|
|
||||||
o.set(myColor, pos);
|
|
||||||
|
|
||||||
let turn;
|
|
||||||
if (o.getPattern(opColor).length > 0) {
|
|
||||||
turn = myColor == 'black' ? game.white_user_id : game.black_user_id;
|
|
||||||
} else {
|
|
||||||
turn = myColor == 'black' ? game.black_user_id : game.white_user_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const log = {
|
|
||||||
at: new Date(),
|
|
||||||
color: myColor,
|
|
||||||
pos
|
|
||||||
};
|
|
||||||
|
|
||||||
await Game.update({
|
|
||||||
_id: gameId
|
|
||||||
}, {
|
|
||||||
$set: {
|
|
||||||
turn_user_id: turn
|
|
||||||
},
|
|
||||||
$push: {
|
|
||||||
logs: log
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
publishOthelloGameStream(gameId, 'set', {
|
|
||||||
color: myColor,
|
|
||||||
pos
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function set(pos) {
|
||||||
|
const game = await Game.findOne({ _id: gameId });
|
||||||
|
|
||||||
|
if (game.is_ended) return;
|
||||||
|
|
||||||
|
const o = new Othello();
|
||||||
|
|
||||||
|
game.logs.forEach(log => {
|
||||||
|
o.set(log.color, log.pos);
|
||||||
|
});
|
||||||
|
|
||||||
|
const myColor = game.black_user_id.equals(user._id) ? 'black' : 'white';
|
||||||
|
const opColor = myColor == 'black' ? 'white' : 'black';
|
||||||
|
|
||||||
|
if (!o.canReverse(myColor, pos)) return;
|
||||||
|
o.set(myColor, pos);
|
||||||
|
|
||||||
|
let turn;
|
||||||
|
if (o.getPattern(opColor).length > 0) {
|
||||||
|
turn = myColor == 'black' ? game.white_user_id : game.black_user_id;
|
||||||
|
} else if (o.getPattern(myColor).length > 0) {
|
||||||
|
turn = myColor == 'black' ? game.black_user_id : game.white_user_id;
|
||||||
|
} else {
|
||||||
|
turn = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isEnded = turn === null;
|
||||||
|
|
||||||
|
let winner;
|
||||||
|
if (isEnded) {
|
||||||
|
const blackCount = o.board.filter(s => s == 'black').length;
|
||||||
|
const whiteCount = o.board.filter(s => s == 'white').length;
|
||||||
|
winner = blackCount == whiteCount ? null : blackCount > whiteCount ? game.black_user_id : game.white_user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const log = {
|
||||||
|
at: new Date(),
|
||||||
|
color: myColor,
|
||||||
|
pos
|
||||||
|
};
|
||||||
|
|
||||||
|
await Game.update({
|
||||||
|
_id: gameId
|
||||||
|
}, {
|
||||||
|
$set: {
|
||||||
|
turn_user_id: turn,
|
||||||
|
is_ended: isEnded,
|
||||||
|
winner_id: winner
|
||||||
|
},
|
||||||
|
$push: {
|
||||||
|
logs: log
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
publishOthelloGameStream(gameId, 'set', {
|
||||||
|
color: myColor,
|
||||||
|
pos
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<header><b>{{ game.black_user.name }}</b>(黒) vs <b>{{ game.white_user.name }}</b>(白)</header>
|
<header><b>{{ game.black_user.name }}</b>(黒) vs <b>{{ game.white_user.name }}</b>(白)</header>
|
||||||
<p class="turn">{{ turn ? 'あなたのターンです' : '相手のターンです' }}<mk-ellipsis v-if="!turn"/></p>
|
<p class="turn" v-if="!iAmPlayer && !isEnded">{{ turn.name }}のターンです<mk-ellipsis/></p>
|
||||||
|
<p class="turn" v-if="iAmPlayer && !isEnded">{{ isMyTurn ? 'あなたのターンです' : '相手のターンです' }}<mk-ellipsis v-if="!isMyTurn"/></p>
|
||||||
|
<p class="result" v-if="isEnded">
|
||||||
|
<template v-if="winner"><b>{{ winner.name }}</b>の勝ち</template>
|
||||||
|
<template v-else>引き分け</template>
|
||||||
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<div v-for="(stone, i) in o.board"
|
<div v-for="(stone, i) in o.board"
|
||||||
:class="{ empty: stone == null, myTurn: turn, can: o.canReverse(turn ? myColor : opColor, i) }"
|
:class="{ empty: stone == null, myTurn: isMyTurn, can: o.canReverse(turn.id == game.black_user.id ? 'black' : 'white', i) }"
|
||||||
@click="set(i)"
|
@click="set(i)"
|
||||||
>
|
>
|
||||||
<img v-if="stone == 'black'" :src="`${game.black_user.avatar_url}?thumbnail&size=64`" alt="">
|
<img v-if="stone == 'black'" :src="`${game.black_user.avatar_url}?thumbnail&size=64`" alt="">
|
||||||
|
@ -25,10 +30,16 @@ export default Vue.extend({
|
||||||
return {
|
return {
|
||||||
o: new Othello(),
|
o: new Othello(),
|
||||||
turn: null,
|
turn: null,
|
||||||
|
isMyTurn: null,
|
||||||
|
isEnded: false,
|
||||||
|
winner: null,
|
||||||
connection: null
|
connection: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
iAmPlayer(): boolean {
|
||||||
|
return this.game.black_user_id == (this as any).os.i.id || this.game.white_user_id == (this as any).os.i.id;
|
||||||
|
},
|
||||||
myColor(): string {
|
myColor(): string {
|
||||||
return this.game.black_user_id == (this as any).os.i.id ? 'black' : 'white';
|
return this.game.black_user_id == (this as any).os.i.id ? 'black' : 'white';
|
||||||
},
|
},
|
||||||
|
@ -41,7 +52,10 @@ export default Vue.extend({
|
||||||
this.o.set(log.color, log.pos);
|
this.o.set(log.color, log.pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.turn = this.game.turn_user_id == (this as any).os.i.id;
|
this.turn = this.game.turn_user_id == this.game.black_user_id ? this.game.black_user : this.game.white_user;
|
||||||
|
this.isMyTurn = this.game.turn_user_id == (this as any).os.i.id;
|
||||||
|
this.isEnded = this.game.is_ended;
|
||||||
|
this.winner = this.game.winner;
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.connection = new OthelloGameStream((this as any).os.i, this.game);
|
this.connection = new OthelloGameStream((this as any).os.i, this.game);
|
||||||
|
@ -53,11 +67,17 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
set(pos) {
|
set(pos) {
|
||||||
if (!this.turn) return;
|
if (!this.isMyTurn) return;
|
||||||
if (!this.o.canReverse(this.myColor, pos)) return;
|
if (!this.o.canReverse(this.myColor, pos)) return;
|
||||||
this.o.set(this.myColor, pos);
|
this.o.set(this.myColor, pos);
|
||||||
if (this.o.getPattern(this.opColor).length > 0) {
|
if (this.o.getPattern(this.opColor).length > 0) {
|
||||||
this.turn = !this.turn;
|
this.isMyTurn = !this.isMyTurn;
|
||||||
|
this.turn = this.myColor == 'black' ? this.game.white_user : this.game.black_user;
|
||||||
|
} else if (this.o.getPattern(this.myColor).length == 0) {
|
||||||
|
this.isEnded = true;
|
||||||
|
const blackCount = this.o.board.filter(s => s == 'black').length;
|
||||||
|
const whiteCount = this.o.board.filter(s => s == 'white').length;
|
||||||
|
this.winner = blackCount == whiteCount ? null : blackCount > whiteCount ? this.game.black_user : this.game.white_user;
|
||||||
}
|
}
|
||||||
this.connection.send({
|
this.connection.send({
|
||||||
type: 'set',
|
type: 'set',
|
||||||
|
@ -67,8 +87,28 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
onSet(x) {
|
onSet(x) {
|
||||||
this.o.set(x.color, x.pos);
|
this.o.set(x.color, x.pos);
|
||||||
if (this.o.getPattern(this.myColor).length > 0) {
|
if (this.o.getPattern('black').length == 0 && this.o.getPattern('white').length == 0) {
|
||||||
this.turn = true;
|
this.isEnded = true;
|
||||||
|
const blackCount = this.o.board.filter(s => s == 'black').length;
|
||||||
|
const whiteCount = this.o.board.filter(s => s == 'white').length;
|
||||||
|
this.winner = blackCount == whiteCount ? null : blackCount > whiteCount ? this.game.black_user : this.game.white_user;
|
||||||
|
} else {
|
||||||
|
if (this.iAmPlayer && this.o.getPattern(this.myColor).length > 0) {
|
||||||
|
this.isMyTurn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x.color == 'black' && this.o.getPattern('white').length > 0) {
|
||||||
|
this.turn = this.game.white_user;
|
||||||
|
}
|
||||||
|
if (x.color == 'black' && this.o.getPattern('white').length == 0) {
|
||||||
|
this.turn = this.game.black_user;
|
||||||
|
}
|
||||||
|
if (x.color == 'white' && this.o.getPattern('black').length > 0) {
|
||||||
|
this.turn = this.game.black_user;
|
||||||
|
}
|
||||||
|
if (x.color == 'white' && this.o.getPattern('black').length == 0) {
|
||||||
|
this.turn = this.game.white_user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,17 @@
|
||||||
<img :src="`${g.black_user.avatar_url}?thumbnail&size=32`" alt="">
|
<img :src="`${g.black_user.avatar_url}?thumbnail&size=32`" alt="">
|
||||||
<img :src="`${g.white_user.avatar_url}?thumbnail&size=32`" alt="">
|
<img :src="`${g.white_user.avatar_url}?thumbnail&size=32`" alt="">
|
||||||
<span><b>{{ g.black_user.name }}</b> vs <b>{{ g.white_user.name }}</b></span>
|
<span><b>{{ g.black_user.name }}</b> vs <b>{{ g.white_user.name }}</b></span>
|
||||||
<span class="state">{{ g.winner ? '終了' : '進行中' }}</span>
|
<span class="state">{{ g.is_ended ? '終了' : '進行中' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section v-if="games.length > 0">
|
||||||
<h2>みんなの対局</h2>
|
<h2>みんなの対局</h2>
|
||||||
|
<div class="game" v-for="g in games" tabindex="-1" @click="game = g">
|
||||||
|
<img :src="`${g.black_user.avatar_url}?thumbnail&size=32`" alt="">
|
||||||
|
<img :src="`${g.white_user.avatar_url}?thumbnail&size=32`" alt="">
|
||||||
|
<span><b>{{ g.black_user.name }}</b> vs <b>{{ g.white_user.name }}</b></span>
|
||||||
|
<span class="state">{{ g.is_ended ? '終了' : '進行中' }}</span>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue