From 910ccf1804033a940a36273e21d4a586a26a6145 Mon Sep 17 00:00:00 2001
From: syuilo
Date: Fri, 9 Mar 2018 18:11:10 +0900
Subject: [PATCH] =?UTF-8?q?=E3=81=AA=E3=82=93=E3=81=8B=E3=82=82=E3=81=86?=
=?UTF-8?q?=E3=82=81=E3=81=A3=E3=81=A1=E3=82=83=E5=A4=89=E3=81=88=E3=81=9F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/endpoints/othello/games.ts | 41 +-
src/api/endpoints/othello/match.ts | 2 +-
src/api/models/othello-game.ts | 16 +-
src/common/othello/core.ts | 33 +-
src/common/othello/maps.ts | 618 ++++++++++--------
.../common/views/components/othello.game.vue | 6 +-
.../common/views/components/othello.room.vue | 16 +-
7 files changed, 425 insertions(+), 307 deletions(-)
diff --git a/src/api/endpoints/othello/games.ts b/src/api/endpoints/othello/games.ts
index dd9fb5ef5..dd3ee523a 100644
--- a/src/api/endpoints/othello/games.ts
+++ b/src/api/endpoints/othello/games.ts
@@ -6,6 +6,23 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
const [my = false, myErr] = $(params.my).optional.boolean().$;
if (myErr) return rej('invalid my param');
+ // Get 'limit' parameter
+ const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
+ if (limitErr) return rej('invalid limit param');
+
+ // Get 'since_id' parameter
+ const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$;
+ if (sinceIdErr) return rej('invalid since_id param');
+
+ // Get 'until_id' parameter
+ const [untilId, untilIdErr] = $(params.until_id).optional.id().$;
+ if (untilIdErr) return rej('invalid until_id param');
+
+ // Check if both of since_id and until_id is specified
+ if (sinceId && untilId) {
+ return rej('cannot set since_id and until_id');
+ }
+
const q = my ? {
is_started: true,
$or: [{
@@ -17,13 +34,29 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
is_started: true
};
+
+ const sort = {
+ _id: -1
+ };
+
+ if (sinceId) {
+ sort._id = 1;
+ q._id = {
+ $gt: sinceId
+ };
+ } else if (untilId) {
+ q._id = {
+ $lt: untilId
+ };
+ }
+
// Fetch games
const games = await Game.find(q, {
- sort: {
- _id: -1
- }
+ sort
});
// Reponse
- res(Promise.all(games.map(async (g) => await pack(g, user))));
+ res(Promise.all(games.map(async (g) => await pack(g, user, {
+ detail: false
+ }))));
});
diff --git a/src/api/endpoints/othello/match.ts b/src/api/endpoints/othello/match.ts
index 05b87a541..640be9cb5 100644
--- a/src/api/endpoints/othello/match.ts
+++ b/src/api/endpoints/othello/match.ts
@@ -38,7 +38,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
is_ended: false,
logs: [],
settings: {
- map: eighteight,
+ map: eighteight.data,
bw: 'random',
is_llotheo: false
}
diff --git a/src/api/models/othello-game.ts b/src/api/models/othello-game.ts
index de7c804c4..7ae48b8aa 100644
--- a/src/api/models/othello-game.ts
+++ b/src/api/models/othello-game.ts
@@ -28,7 +28,7 @@ export interface IGame {
winner_id: mongo.ObjectID;
logs: any[];
settings: {
- map: Map;
+ map: string[];
bw: string | number;
is_llotheo: boolean;
};
@@ -39,8 +39,15 @@ export interface IGame {
*/
export const pack = (
game: any,
- me?: string | mongo.ObjectID | IUser
+ me?: string | mongo.ObjectID | IUser,
+ options?: {
+ detail?: boolean
+ }
) => new Promise(async (resolve, reject) => {
+ const opts = Object.assign({
+ detail: true
+ }, options);
+
let _game: any;
// Populate the game if 'game' is ID
@@ -69,6 +76,11 @@ export const pack = (
_game.id = _game._id;
delete _game._id;
+ if (opts.detail === false) {
+ delete _game.logs;
+ delete _game.settings.map;
+ }
+
// Populate user
_game.user1 = await packUser(_game.user1_id, meId);
_game.user2 = await packUser(_game.user2_id, meId);
diff --git a/src/common/othello/core.ts b/src/common/othello/core.ts
index b76586031..0b4cb1fc1 100644
--- a/src/common/othello/core.ts
+++ b/src/common/othello/core.ts
@@ -1,5 +1,3 @@
-import { Map } from './maps';
-
export type Color = 'black' | 'white';
export type MapPixel = 'null' | 'empty';
@@ -11,12 +9,14 @@ export type Options = {
* オセロエンジン
*/
export default class Othello {
- public map: Map;
- public mapData: MapPixel[];
+ public map: MapPixel[];
+ public mapWidth: number;
+ public mapHeight: number;
public board: Color[];
public turn: Color = 'black';
public opts: Options;
+ public prevPos = -1;
public stats: Array<{
b: number;
w: number;
@@ -25,18 +25,21 @@ export default class Othello {
/**
* ゲームを初期化します
*/
- constructor(map: Map, opts: Options) {
- this.map = map;
+ constructor(map: string[], opts: Options) {
this.opts = opts;
+ this.mapWidth = map[0].length;
+ this.mapHeight = map.length;
+ const mapData = map.join('');
+
// Parse map data
- this.board = this.map.data.split('').map(d => {
+ this.board = mapData.split('').map(d => {
if (d == '-') return null;
if (d == 'b') return 'black';
if (d == 'w') return 'white';
return undefined;
});
- this.mapData = this.map.data.split('').map(d => {
+ this.map = mapData.split('').map(d => {
if (d == '-' || d == 'b' || d == 'w') return 'empty';
return 'null';
});
@@ -48,8 +51,6 @@ export default class Othello {
}];
}
- public prevPos = -1;
-
/**
* 黒石の数
*/
@@ -79,13 +80,13 @@ export default class Othello {
}
public transformPosToXy(pos: number): number[] {
- const x = pos % this.map.size;
- const y = Math.floor(pos / this.map.size);
+ const x = pos % this.mapWidth;
+ const y = Math.floor(pos / this.mapHeight);
return [x, y];
}
public transformXyToPos(x: number, y: number): number {
- return x + (y * this.map.size);
+ return x + (y * this.mapHeight);
}
/**
@@ -145,8 +146,8 @@ export default class Othello {
* @param pos 位置
*/
public mapDataGet(pos: number): MapPixel {
- if (pos < 0 || pos >= this.mapData.length) return 'null';
- return this.mapData[pos];
+ if (pos < 0 || pos >= this.map.length) return 'null';
+ return this.map[pos];
}
/**
@@ -188,7 +189,7 @@ export default class Othello {
const found = [];
while (true) {
const [x, y] = fn(i);
- if (x < 0 || y < 0 || x >= this.map.size || y >= this.map.size) break;
+ if (x < 0 || y < 0 || x >= this.mapWidth || y >= this.mapHeight) break;
const pos = this.transformXyToPos(x, y);
const pixel = this.mapDataGet(pos);
if (pixel == 'null') break;
diff --git a/src/common/othello/maps.ts b/src/common/othello/maps.ts
index 434fd75af..d8f3154a0 100644
--- a/src/common/othello/maps.ts
+++ b/src/common/othello/maps.ts
@@ -11,438 +11,502 @@
export type Map = {
name?: string;
category?: string;
- size: number;
- data: string;
+ author?: string;
+ data: string[];
};
export const fourfour: Map = {
name: '4x4',
category: '4x4',
- size: 4,
- data:
- '----' +
- '-wb-' +
- '-bw-' +
+ data: [
+ '----',
+ '-wb-',
+ '-bw-',
'----'
+ ]
};
export const sixsix: Map = {
name: '6x6',
category: '6x6',
- size: 6,
- data:
- '------' +
- '------' +
- '--wb--' +
- '--bw--' +
- '------' +
+ data: [
+ '------',
+ '------',
+ '--wb--',
+ '--bw--',
+ '------',
'------'
+ ]
};
export const roundedSixsix: Map = {
name: '6x6 rounded',
category: '6x6',
- size: 6,
- data:
- ' ---- ' +
- '------' +
- '--wb--' +
- '--bw--' +
- '------' +
+ author: 'syuilo',
+ data: [
+ ' ---- ',
+ '------',
+ '--wb--',
+ '--bw--',
+ '------',
' ---- '
+ ]
};
export const roundedSixsix2: Map = {
name: '6x6 rounded 2',
category: '6x6',
- size: 6,
- data:
- ' -- ' +
- ' ---- ' +
- '--wb--' +
- '--bw--' +
- ' ---- ' +
+ author: 'syuilo',
+ data: [
+ ' -- ',
+ ' ---- ',
+ '--wb--',
+ '--bw--',
+ ' ---- ',
' -- '
+ ]
};
export const eighteight: Map = {
name: '8x8',
category: '8x8',
- size: 8,
- data:
- '--------' +
- '--------' +
- '--------' +
- '---wb---' +
- '---bw---' +
- '--------' +
- '--------' +
+ data: [
+ '--------',
+ '--------',
+ '--------',
+ '---wb---',
+ '---bw---',
+ '--------',
+ '--------',
'--------'
+ ]
};
export const roundedEighteight: Map = {
name: '8x8 rounded',
category: '8x8',
- size: 8,
- data:
- ' ------ ' +
- '--------' +
- '--------' +
- '---wb---' +
- '---bw---' +
- '--------' +
- '--------' +
+ author: 'syuilo',
+ data: [
+ ' ------ ',
+ '--------',
+ '--------',
+ '---wb---',
+ '---bw---',
+ '--------',
+ '--------',
' ------ '
+ ]
};
export const roundedEighteight2: Map = {
name: '8x8 rounded 2',
category: '8x8',
- size: 8,
- data:
- ' ---- ' +
- ' ------ ' +
- '--------' +
- '---wb---' +
- '---bw---' +
- '--------' +
- ' ------ ' +
+ author: 'syuilo',
+ data: [
+ ' ---- ',
+ ' ------ ',
+ '--------',
+ '---wb---',
+ '---bw---',
+ '--------',
+ ' ------ ',
' ---- '
+ ]
};
export const roundedEighteight3: Map = {
name: '8x8 rounded 3',
category: '8x8',
- size: 8,
- data:
- ' -- ' +
- ' ---- ' +
- ' ------ ' +
- '---wb---' +
- '---bw---' +
- ' ------ ' +
- ' ---- ' +
+ author: 'syuilo',
+ data: [
+ ' -- ',
+ ' ---- ',
+ ' ------ ',
+ '---wb---',
+ '---bw---',
+ ' ------ ',
+ ' ---- ',
' -- '
+ ]
};
export const eighteightWithNotch: Map = {
name: '8x8 with notch',
category: '8x8',
- size: 8,
- data:
- '--- ---' +
- '--------' +
- '--------' +
- ' --wb-- ' +
- ' --bw-- ' +
- '--------' +
- '--------' +
+ author: 'syuilo',
+ data: [
+ '--- ---',
+ '--------',
+ '--------',
+ ' --wb-- ',
+ ' --bw-- ',
+ '--------',
+ '--------',
'--- ---'
+ ]
};
export const eighteightWithSomeHoles: Map = {
name: '8x8 with some holes',
category: '8x8',
- size: 8,
- data:
- '--- ----' +
- '----- --' +
- '-- -----' +
- '---wb---' +
- '---bw- -' +
- ' -------' +
- '--- ----' +
+ author: 'syuilo',
+ data: [
+ '--- ----',
+ '----- --',
+ '-- -----',
+ '---wb---',
+ '---bw- -',
+ ' -------',
+ '--- ----',
'--------'
+ ]
};
export const circle: Map = {
name: 'Circle',
category: '8x8',
- size: 8,
- data:
- ' -- ' +
- ' ------ ' +
- ' ------ ' +
- '---wb---' +
- '---bw---' +
- ' ------ ' +
- ' ------ ' +
+ author: 'syuilo',
+ data: [
+ ' -- ',
+ ' ------ ',
+ ' ------ ',
+ '---wb---',
+ '---bw---',
+ ' ------ ',
+ ' ------ ',
' -- '
+ ]
};
-export const face: Map = {
- name: 'Face',
+export const smile: Map = {
+ name: 'Smile',
category: '8x8',
- size: 8,
- data:
- ' ------ ' +
- '--------' +
- '-- -- --' +
- '---wb---' +
- '-- bw --' +
- '--- ---' +
- '--------' +
+ author: 'syuilo',
+ data: [
+ ' ------ ',
+ '--------',
+ '-- -- --',
+ '---wb---',
+ '-- bw --',
+ '--- ---',
+ '--------',
' ------ '
+ ]
};
export const window: Map = {
name: 'Window',
category: '8x8',
- size: 8,
- data:
- '--------' +
- '- -- -' +
- '- -- -' +
- '---wb---' +
- '---bw---' +
- '- -- -' +
- '- -- -' +
+ author: 'syuilo',
+ data: [
+ '--------',
+ '- -- -',
+ '- -- -',
+ '---wb---',
+ '---bw---',
+ '- -- -',
+ '- -- -',
'--------'
+ ]
};
export const reserved: Map = {
name: 'Reserved',
category: '8x8',
- size: 8,
- data:
- 'w------b' +
- '--------' +
- '--------' +
- '---wb---' +
- '---bw---' +
- '--------' +
- '--------' +
+ author: 'Aya',
+ data: [
+ 'w------b',
+ '--------',
+ '--------',
+ '---wb---',
+ '---bw---',
+ '--------',
+ '--------',
'b------w'
+ ]
};
export const x: Map = {
name: 'X',
category: '8x8',
- size: 8,
- data:
- 'w------b' +
- '-w----b-' +
- '--w--b--' +
- '---wb---' +
- '---bw---' +
- '--b--w--' +
- '-b----w-' +
+ author: 'Aya',
+ data: [
+ 'w------b',
+ '-w----b-',
+ '--w--b--',
+ '---wb---',
+ '---bw---',
+ '--b--w--',
+ '-b----w-',
'b------w'
+ ]
+};
+
+export const minesweeper: Map = {
+ name: 'Minesweeper',
+ category: '8x8',
+ author: 'syuilo',
+ data: [
+ 'b-b--w-w',
+ '-w-wb-b-',
+ 'w-b--w-b',
+ '-b-wb-w-',
+ '-w-bw-b-',
+ 'b-w--b-w',
+ '-b-bw-w-',
+ 'w-w--b-b'
+ ]
};
export const tenthtenth: Map = {
name: '10x10',
category: '10x10',
- size: 10,
- data:
- '----------' +
- '----------' +
- '----------' +
- '----------' +
- '----wb----' +
- '----bw----' +
- '----------' +
- '----------' +
- '----------' +
+ data: [
+ '----------',
+ '----------',
+ '----------',
+ '----------',
+ '----wb----',
+ '----bw----',
+ '----------',
+ '----------',
+ '----------',
'----------'
+ ]
};
export const hole: Map = {
name: 'The Hole',
category: '10x10',
- size: 10,
- data:
- '----------' +
- '----------' +
- '--wb--wb--' +
- '--bw--bw--' +
- '---- ----' +
- '---- ----' +
- '--wb--wb--' +
- '--bw--bw--' +
- '----------' +
+ author: 'syuilo',
+ data: [
+ '----------',
+ '----------',
+ '--wb--wb--',
+ '--bw--bw--',
+ '---- ----',
+ '---- ----',
+ '--wb--wb--',
+ '--bw--bw--',
+ '----------',
'----------'
+ ]
};
export const grid: Map = {
name: 'Grid',
category: '10x10',
- size: 10,
- data:
- '----------' +
- '- - -- - -' +
- '----------' +
- '- - -- - -' +
- '----wb----' +
- '----bw----' +
- '- - -- - -' +
- '----------' +
- '- - -- - -' +
+ author: 'syuilo',
+ data: [
+ '----------',
+ '- - -- - -',
+ '----------',
+ '- - -- - -',
+ '----wb----',
+ '----bw----',
+ '- - -- - -',
+ '----------',
+ '- - -- - -',
'----------'
+ ]
};
export const cross: Map = {
name: 'Cross',
category: '10x10',
- size: 10,
- data:
- ' ---- ' +
- ' ---- ' +
- ' ---- ' +
- '----------' +
- '----wb----' +
- '----bw----' +
- '----------' +
- ' ---- ' +
- ' ---- ' +
+ author: 'Aya',
+ data: [
+ ' ---- ',
+ ' ---- ',
+ ' ---- ',
+ '----------',
+ '----wb----',
+ '----bw----',
+ '----------',
+ ' ---- ',
+ ' ---- ',
' ---- '
+ ]
+};
+
+export const charX: Map = {
+ name: 'Char X',
+ category: '10x10',
+ author: 'syuilo',
+ data: [
+ '--- ---',
+ '---- ----',
+ '----------',
+ ' -------- ',
+ ' --wb-- ',
+ ' --bw-- ',
+ ' -------- ',
+ '----------',
+ '---- ----',
+ '--- ---'
+ ]
+};
+
+export const charY: Map = {
+ name: 'Char Y',
+ category: '10x10',
+ author: 'syuilo',
+ data: [
+ '--- ---',
+ '---- ----',
+ '----------',
+ ' -------- ',
+ ' --wb-- ',
+ ' --bw-- ',
+ ' ------ ',
+ ' ------ ',
+ ' ------ ',
+ ' ------ '
+ ]
};
export const walls: Map = {
name: 'Walls',
category: '10x10',
- size: 10,
- data:
- ' bbbbbbbb ' +
- 'w--------w' +
- 'w--------w' +
- 'w--------w' +
- 'w---wb---w' +
- 'w---bw---w' +
- 'w--------w' +
- 'w--------w' +
- 'w--------w' +
+ author: 'Aya',
+ data: [
+ ' bbbbbbbb ',
+ 'w--------w',
+ 'w--------w',
+ 'w--------w',
+ 'w---wb---w',
+ 'w---bw---w',
+ 'w--------w',
+ 'w--------w',
+ 'w--------w',
' bbbbbbbb '
+ ]
};
export const checker: Map = {
name: 'Checker',
category: '10x10',
- size: 10,
- data:
- '----------' +
- '----------' +
- '----------' +
- '---wbwb---' +
- '---bwbw---' +
- '---wbwb---' +
- '---bwbw---' +
- '----------' +
- '----------' +
+ author: 'Aya',
+ data: [
+ '----------',
+ '----------',
+ '----------',
+ '---wbwb---',
+ '---bwbw---',
+ '---wbwb---',
+ '---bwbw---',
+ '----------',
+ '----------',
'----------'
+ ]
};
export const sixeight: Map = {
name: '6x8',
category: 'special',
- size: 8,
- data:
- ' ------ ' +
- ' ------ ' +
- ' ------ ' +
- ' --wb-- ' +
- ' --bw-- ' +
- ' ------ ' +
- ' ------ ' +
- ' ------ '
+ data: [
+ '------',
+ '------',
+ '------',
+ '--wb--',
+ '--bw--',
+ '------',
+ '------',
+ '------'
+ ]
};
export const spark: Map = {
name: 'Spark',
category: 'special',
- size: 10,
- data:
- ' - - ' +
- '----------' +
- ' -------- ' +
- ' -------- ' +
- ' ---wb--- ' +
- ' ---bw--- ' +
- ' -------- ' +
- ' -------- ' +
- '----------' +
+ author: 'syuilo',
+ data: [
+ ' - - ',
+ '----------',
+ ' -------- ',
+ ' -------- ',
+ ' ---wb--- ',
+ ' ---bw--- ',
+ ' -------- ',
+ ' -------- ',
+ '----------',
' - - '
+ ]
};
export const islands: Map = {
name: 'Islands',
category: 'special',
- size: 10,
- data:
- '-------- ' +
- '---wb--- ' +
- '---bw--- ' +
- '-------- ' +
- ' - - ' +
- ' - - ' +
- ' --------' +
- ' --------' +
- ' --------' +
+ author: 'syuilo',
+ data: [
+ '-------- ',
+ '---wb--- ',
+ '---bw--- ',
+ '-------- ',
+ ' - - ',
+ ' - - ',
+ ' --------',
+ ' --------',
+ ' --------',
' --------'
+ ]
};
export const iphonex: Map = {
name: 'iPhone X',
category: 'special',
- size: 12,
- data:
- ' -- -- ' +
- ' -------- ' +
- ' -------- ' +
- ' -------- ' +
- ' -------- ' +
- ' ---wb--- ' +
- ' ---bw--- ' +
- ' -------- ' +
- ' -------- ' +
- ' -------- ' +
- ' -------- ' +
- ' ------ '
+ author: 'syuilo',
+ data: [
+ ' -- -- ',
+ '--------',
+ '--------',
+ '--------',
+ '--------',
+ '---wb---',
+ '---bw---',
+ '--------',
+ '--------',
+ '--------',
+ '--------',
+ ' ------ '
+ ]
};
export const bigBoard: Map = {
name: 'Big board',
category: 'special',
- size: 16,
- data:
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '-------wb-------' +
- '-------bw-------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
- '----------------' +
+ data: [
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '-------wb-------',
+ '-------bw-------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
+ '----------------',
'----------------'
+ ]
};
export const twoBoard: Map = {
name: 'Two board',
category: 'special',
- size: 17,
- data:
- '-------- --------' +
- '-------- --------' +
- '-------- --------' +
- '---wb--- ---wb---' +
- '---bw--- ---bw---' +
- '-------- --------' +
- '-------- --------' +
- '-------- --------' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' '
+ author: 'Aya',
+ data: [
+ '-------- --------',
+ '-------- --------',
+ '-------- --------',
+ '---wb--- ---wb---',
+ '---bw--- ---bw---',
+ '-------- --------',
+ '-------- --------',
+ '-------- --------'
+ ]
};
diff --git a/src/web/app/common/views/components/othello.game.vue b/src/web/app/common/views/components/othello.game.vue
index ffda68c8d..248528ed4 100644
--- a/src/web/app/common/views/components/othello.game.vue
+++ b/src/web/app/common/views/components/othello.game.vue
@@ -10,9 +10,9 @@
引き分け
-
+
![]()
@@ -106,6 +106,8 @@ export default Vue.extend({
this.o.put(log.color, log.pos);
});
+ console.log(this.o);
+
this.logs = this.game.logs;
this.logPos = this.logs.length;
},
diff --git a/src/web/app/common/views/components/othello.room.vue b/src/web/app/common/views/components/othello.room.vue
index bcae37b22..0fcca8548 100644
--- a/src/web/app/common/views/components/othello.room.vue
+++ b/src/web/app/common/views/components/othello.room.vue
@@ -4,14 +4,17 @@
ゲームの設定
-
+
-
+
+ {{ m.name }}
+ (by {{ m.author }})
+
-
-
+
%fa:circle%
@@ -112,7 +115,7 @@ export default Vue.extend({
},
onMapChange(v) {
- this.game.settings.map = Object.entries(maps).find(x => x[1].name == v)[1];
+ this.game.settings.map = Object.entries(maps).find(x => x[1].name == v)[1].data;
this.connection.send({
type: 'update-settings',
settings: this.game.settings
@@ -141,6 +144,9 @@ export default Vue.extend({
padding 8px
border-bottom dashed 1px #c4cdd4
+ > .map
+ width 300px
+
> .board
display grid
grid-gap 4px