diff --git a/src/containers/ruby-tab/koshien-snippets.json b/src/containers/ruby-tab/koshien-snippets.json
new file mode 100644
index 00000000000..13f63e9497b
--- /dev/null
+++ b/src/containers/ruby-tab/koshien-snippets.json
@@ -0,0 +1,78 @@
+{
+ "koshien.move_to": {
+ "snippet": "koshien.move_to([${1:0},${2:0}])",
+ "description": "x座標 (0) y座標 (0) に移動する"
+ },
+ "koshien.get_map_area": {
+ "snippet": "koshien.get_map_area([${1:0},${2:0}])",
+ "description": "x座標 (0) y座標 (0) 付近のマップ情報を取得"
+ },
+ "koshien.calc_route": {
+ "snippet": "koshien.calc_route(src:'${1:0:0}',dst:'${2:0:0}' except_cells:${3:1}])",
+ "description": "2点間の最短距離 始点 x座標 (0) y座標 (0) 終点 x座標 (0) y座標 (0) 通らない道 リスト (0)"
+ },
+ "koshien.set_dynamite": {
+ "snippet": "koshien.set_dynamite([${1:0},${2:0}])",
+ "description": "ダイナマイトをx座標 (0) y座標 (0) に置く"
+ },
+ "koshien.set_bomb": {
+ "snippet": "koshien.set_bomb([${1:0},${2:0}])",
+ "description": "爆弾をx座標 (0) y座標 (0) に置く"
+ },
+ "koshien.map": {
+ "snippet": "koshien.map(${1:0},${2:0} on:${3:'map_1'})",
+ "description": "x座標 (0) y座標 (0) のマップ情報を('map_1')に保存"
+ },
+ "koshien.map_all": {
+ "snippet": "koshien.map_all(save_as:${'map_1'})",
+ "description": "マップ情報を('map_1')に保存"
+ },
+ "koshien.other_player_x": {
+ "snippet": "koshien.other_player_x",
+ "description": "対戦キャラクタの x座標"
+ },
+ "koshien.other_player_y": {
+ "snippet": "koshien.other_player_y",
+ "description": "対戦キャラクタの y座標"
+ },
+ "koshien.player_x": {
+ "snippet": "koshien.player_x",
+ "description": "プレイヤーの x座標"
+ },
+ "koshien.player_y": {
+ "snippet": "koshien.player_y",
+ "description": "プレイヤーの y座標"
+ },
+ "koshien.enemy_x": {
+ "snippet": "koshien.enemy_x",
+ "description": "妨害キャラクタの x座標"
+ },
+ "koshien.enemy_y": {
+ "snippet": "koshien.enemy_y",
+ "description": "妨害キャラクタの y座標"
+ },
+ "koshien.goal_x": {
+ "snippet": "koshien.goal_x",
+ "description": "ゴールの x座標"
+ },
+ "koshien.goal_y": {
+ "snippet": "koshien.goal_y",
+ "description": "ゴールの y座標"
+ },
+ "koshien.turn_over": {
+ "snippet": "koshien.turn_over",
+ "description": "ターンを終了する"
+ },
+ "koshien.connect_game": {
+ "snippet": "koshien.connect_game(player_name:${1:'test'})",
+ "description": "プレイヤー名('test')ゲームに接続する"
+ },
+ "koshien.position_x": {
+ "snippet": "koshien.position_x(${1:'0:0'})",
+ "description": "('0:0')のx座標"
+ },
+ "koshien.position_y": {
+ "snippet": "koshien.position_y(${1:'0:0'})",
+ "description": "('0:0')のy座標"
+ }
+}
\ No newline at end of file
diff --git a/src/containers/ruby-tab/snippets-completer.js b/src/containers/ruby-tab/snippets-completer.js
index 4df893ea11e..506e4372f29 100644
--- a/src/containers/ruby-tab/snippets-completer.js
+++ b/src/containers/ruby-tab/snippets-completer.js
@@ -19,7 +19,7 @@ import MicrobitSnippets from './microbit-snippets.json';
import MeshSnippets from './mesh-snippets.json';
import SmalrubotS1Snippets from './smalrubot-s1-snippets.json';
import MicrobitMoreSnippets from './microbit-more-snippets.json';
-
+import KoshienSnippets from './koshien-snippets.json';
class SnippetsCompleter extends BaseCompleter {
#completions = [];
@@ -45,7 +45,8 @@ class SnippetsCompleter extends BaseCompleter {
MicrobitSnippets,
MeshSnippets,
SmalrubotS1Snippets,
- MicrobitMoreSnippets
+ MicrobitMoreSnippets,
+ KoshienSnippets
];
snippetsList.forEach(snippets => {
for (const [caption, item] of Object.entries(snippets)) {
diff --git a/src/lib/libraries/extensions/index.jsx b/src/lib/libraries/extensions/index.jsx
index 8b05eb7672a..9fbcbfc744f 100644
--- a/src/lib/libraries/extensions/index.jsx
+++ b/src/lib/libraries/extensions/index.jsx
@@ -396,6 +396,26 @@ const extensions = [
/>
),
helpLink: 'https://github.com/smalruby/smalruby3-gui/wiki/SmalrubotS1'
+ },
+ {
+ name: (
+
+ ),
+ extensionId: 'koshien',
+ iconURL: musicIconURL,
+ insetIconURL: musicInsetIconURL,
+ description: (
+
+ ),
+ featured: true
}
];
diff --git a/src/lib/ruby-generator/index.js b/src/lib/ruby-generator/index.js
index 8fd3689ad44..624394daefb 100644
--- a/src/lib/ruby-generator/index.js
+++ b/src/lib/ruby-generator/index.js
@@ -30,6 +30,7 @@ import WeDo2Blocks from './wedo2.js';
import GdxForBlocks from './gdx_for.js';
import MeshBlocks from './mesh.js';
import SmalrubotS1Blocks from './smalrubot_s1.js';
+import koshien from './koshien.js';
const SCALAR_TYPE = '';
const LIST_TYPE = 'list';
@@ -462,5 +463,6 @@ WeDo2Blocks(RubyGenerator);
GdxForBlocks(RubyGenerator);
MeshBlocks(RubyGenerator);
SmalrubotS1Blocks(RubyGenerator);
+koshien(RubyGenerator);
export default RubyGenerator;
diff --git a/src/lib/ruby-generator/koshien.js b/src/lib/ruby-generator/koshien.js
new file mode 100644
index 00000000000..f9223037f15
--- /dev/null
+++ b/src/lib/ruby-generator/koshien.js
@@ -0,0 +1,70 @@
+/**
+ * Define Ruby code generator for Microbit More Blocks
+ * @param {RubyGenerator} Generator The RubyGenerator
+ * @return {RubyGenerator} same as param.
+ */
+
+export default function (Generator) {
+ Generator.koshien_move_to = function (block) {
+ const x = Generator.valueToCode(block, 'X', Generator.ORDER_NONE) || 0;
+ const y = Generator.valueToCode(block, 'Y', Generator.ORDER_NONE) || 0;
+ return `koshien.move_to([${x},${y}])\n`;
+ };
+ Generator.koshien_calc_route = function (block) {
+ const src_x = Generator.valueToCode(block, 'SRC_X', Generator.ORDER_NONE) || 0;
+ const src_y = Generator.valueToCode(block, 'SRC_Y', Generator.ORDER_NONE) || 0;
+ const dst_x = Generator.valueToCode(block, 'DST_X', Generator.ORDER_NONE) || 0;
+ const dst_y = Generator.valueToCode(block, 'DST_Y', Generator.ORDER_NONE) || 0;
+ const list = Generator.valueToCode(block, 'LIST', Generator.ORDER_NONE) || 0;
+
+ return [`koshien.calc_route(src:"${src_x}:${src_y}",dst:"${dst_x}:${dst_y}",except_cells:${list})`];
+ };
+ Generator.koshien_get_map_area = function (block) {
+ const x = Generator.valueToCode(block, 'X', Generator.ORDER_NONE) || 0;
+ const y = Generator.valueToCode(block, 'Y', Generator.ORDER_NONE) || 0;
+ return `koshien.get_map_area([${x},${y}])\n`;
+ };
+ Generator.koshien_set_item = function (block) {
+ const item = Generator.getFieldValue(block, 'ITEM') || null;
+ const x = Generator.valueToCode(block, 'X', Generator.ORDER_NONE) || 0;
+ const y = Generator.valueToCode(block, 'Y', Generator.ORDER_NONE) || 0;
+ return `koshien.set_${item}([${x},${y}])\n`;
+ };
+ Generator.koshien_map = function (block) {
+ const x = Generator.valueToCode(block, 'X', Generator.ORDER_NONE) || 0;
+ const y = Generator.valueToCode(block, 'Y', Generator.ORDER_NONE) || 0;
+ const location = Generator.valueToCode(block, 'LOCATION', Generator.ORDER_NONE) || Generator.quote_('map_1');
+ return [`koshien.map(${x},${y}, on: ${location})`];
+ };
+ Generator.koshien_map_all = function (block) {
+ const location = Generator.valueToCode(block, 'LOCATION', Generator.ORDER_NONE) || Generator.quote_('map_1');
+ return [`koshien.map_all(save_as: ${location})`];
+ };
+ Generator.koshien_locate_objects = function (block) {
+ const x = Generator.valueToCode(block, 'X', Generator.ORDER_NONE) || 0;
+ const y = Generator.valueToCode(block, 'Y', Generator.ORDER_NONE) || 0;
+ const size = Generator.valueToCode(block, 'SIZE', Generator.ORDER_NONE) || 5;
+ const item = Generator.valueToCode(block, 'ITEM', Generator.ORDER_NONE) || Generator.quote_('["A","B","C","D"]');
+
+ return [`koshien.locate_objects(sq_size:${size},cent:"${x}:${y}",objects:${item})`];
+ };
+ Generator.koshien_target_coordinate = function (block) {
+ const target = Generator.getFieldValue(block, 'TARGET') || null;
+ const coordinate = Generator.getFieldValue(block, 'COORDINATE') || null;
+ return [`koshien.${target}_${coordinate}`];
+ };
+ Generator.koshien_turn_over = function () {
+ return `koshien.turn_over\n`;
+ };
+ Generator.koshien_connect_game = function (block) {
+ const name = Generator.valueToCode(block, 'NAME', Generator.ORDER_NONE) || Generator.quote_('test');
+ return `koshien.connect_game(player_name:${name})\n`;
+ };
+ Generator.koshien_position_coordinate = function (block) {
+ const where = Generator.valueToCode(block, 'WHERE', Generator.ORDER_NONE) || Generator.quote_('0:0');
+ const coordinate = Generator.getFieldValue(block, 'COORDINATE') || null;
+ return [`koshien.position_${coordinate}(${where})`];
+ };
+
+ return Generator;
+}
diff --git a/src/lib/ruby-to-blocks-converter/index.js b/src/lib/ruby-to-blocks-converter/index.js
index 6082d5a98e8..ae45c71a2f8 100644
--- a/src/lib/ruby-to-blocks-converter/index.js
+++ b/src/lib/ruby-to-blocks-converter/index.js
@@ -33,6 +33,7 @@ import TranslateConverter from './translate';
import MakeyMakeyConverter from './makeymakey';
import VideoConverter from './video';
import Text2SpeechConverter from './text2speech';
+import KoshienConverter from './koshien';
const messages = defineMessages({
couldNotConvertPrimitive: {
@@ -113,7 +114,8 @@ class RubyToBlocksConverter {
Text2SpeechConverter,
Wedo2Converter,
MicrobitMoreConverter,
- MeshConverter
+ MeshConverter,
+ KoshienConverter
].forEach(x => x.register(this));
}
diff --git a/src/lib/ruby-to-blocks-converter/koshien.js b/src/lib/ruby-to-blocks-converter/koshien.js
new file mode 100644
index 00000000000..1af4fa0704c
--- /dev/null
+++ b/src/lib/ruby-to-blocks-converter/koshien.js
@@ -0,0 +1,215 @@
+import {a} from 'bowser';
+
+const Koshien = 'koshien';
+
+const KoshienConverter = {
+ register: function (converter) {
+ converter.registerCallMethod('self', Koshien, 0, params => {
+ const {node} = params;
+
+ return converter.createRubyExpressionBlock(Koshien, node);
+ });
+
+ converter.registerCallMethod(Koshien, 'move_to', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isNumberOrBlock(args[0].value[0])) return null;
+ if (!converter.isNumberOrBlock(args[0].value[1])) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_move_to', 'statement');
+ converter.addNumberInput(block, 'X', 'math_number', args[0].value[0], 0);
+ converter.addNumberInput(block, 'Y', 'math_number', args[0].value[1], 0);
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'calc_route', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isStringOrBlock(args[0].get('sym:src').value)) return null;
+ if (!converter.isStringOrBlock(args[0].get('sym:dst').value)) return null;
+ if (!converter.isNumberOrBlock(args[0].get('sym:except_cells').value)) return null;
+
+ const src = args[0].get('sym:src').value.split(':');
+ const dst = args[0].get('sym:dst').value.split(':');
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_calc_route', 'value');
+ converter.addNumberInput(block, 'SRC_X', 'math_number', Number(src[0]), 0);
+ converter.addNumberInput(block, 'SRC_Y', 'math_number', Number(src[1]), 0);
+ converter.addNumberInput(block, 'DST_X', 'math_number', Number(dst[0]), 0);
+ converter.addNumberInput(block, 'DST_Y', 'math_number', Number(dst[1]), 0);
+ converter.addNumberInput(block, 'LIST', 'math_number', Number(args[0].get('sym:except_cells')), 0);
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'get_map_area', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isNumberOrBlock(args[0].value[0])) return null;
+ if (!converter.isNumberOrBlock(args[0].value[1])) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_get_map_area', 'statement');
+ converter.addNumberInput(block, 'X', 'math_number', args[0].value[0], 0);
+ converter.addNumberInput(block, 'Y', 'math_number', args[0].value[1], 0);
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'set_dynamite', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isNumberOrBlock(args[0].value[0])) return null;
+ if (!converter.isNumberOrBlock(args[0].value[1])) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_set_item', 'statement');
+ converter.addField(block, 'ITEM', 'dynamite');
+ converter.addNumberInput(block, 'X', 'math_number', args[0].value[0], 0);
+ converter.addNumberInput(block, 'Y', 'math_number', args[0].value[1], 0);
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'set_bomb', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isNumberOrBlock(args[0].value[0])) return null;
+ if (!converter.isNumberOrBlock(args[0].value[1])) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_set_item', 'statement');
+ converter.addField(block, 'ITEM', 'bomb');
+ converter.addNumberInput(block, 'X', 'math_number', args[0].value[0], 0);
+ converter.addNumberInput(block, 'Y', 'math_number', args[0].value[1], 0);
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'map', 3, params => {
+ const {receiver, args} = params;
+
+ const location = args[2].get('sym:on').value;
+
+ if (!converter.isNumberOrBlock(args[0])) return null;
+ if (!converter.isNumberOrBlock(args[1])) return null;
+ if (!converter.isStringOrBlock(location)) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_map', 'value');
+ converter.addNumberInput(block, 'X', 'math_number', args[0], 0);
+ converter.addNumberInput(block, 'Y', 'math_number', args[1], 0);
+ converter.addNumberInput(block, 'LOCATION', location, 0);
+
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'map_all', 1, params => {
+ const {receiver, args} = params;
+
+ const location = args[0].get('sym:save_as').value;
+ if (!converter.isStringOrBlock(location)) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_map_all', 'statement');
+ converter.addTextInput(block, 'LOCATION', location, 'map_1');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'locate_objects', 1, params => {
+ const {receiver, args} = params;
+
+ const sq_size = args[0].get('sym:sq_size').value;
+ const cent = args[0].get('sym:cent').value;
+ const objects = args[0].get('sym:objects').value;
+
+ if (!converter.isNumberOrBlock(sq_size)) return null;
+ if (!converter.isStringOrBlock(cent)) return null;
+ if (!converter.isStringOrBlock(objects)) return null;
+
+ const cent_coordinate = cent.split(':');
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_locate_objects', 'value');
+ converter.addNumberInput(block, 'SIZE', 'math_number', sq_size, 0);
+ converter.addNumberInput(block, 'X', 'math_number', Number(cent_coordinate[0]), 0);
+ converter.addNumberInput(block, 'Y', 'math_number', Number(cent_coordinate[1]), 0);
+ converter.addTextInput(block, 'ITEM', objects, '0');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'other_player_x', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'other_player');
+ converter.addField(block, 'COORDINATE', 'x');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'other_player_y', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'other_player');
+ converter.addField(block, 'COORDINATE', 'y');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'enemy_x', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'enemy');
+ converter.addField(block, 'COORDINATE', 'x');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'enemy_y', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'enemy');
+ converter.addField(block, 'COORDINATE', 'y');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'goal_x', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'goal');
+ converter.addField(block, 'COORDINATE', 'x');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'goal_y', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'goal');
+ converter.addField(block, 'COORDINATE', 'y');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'player_x', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'player');
+ converter.addField(block, 'COORDINATE', 'x');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'player_y', 0, params => {
+ const {receiver} = params;
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_target_coordinate', 'value');
+ converter.addField(block, 'TARGET', 'player');
+ converter.addField(block, 'COORDINATE', 'y');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'turn_over', 0, params => {
+ const {receiver} = params;
+ return converter.changeRubyExpressionBlock(receiver, 'koshien_turn_over', 'value');
+ });
+ converter.registerCallMethod(Koshien, 'connect_game', 1, params => {
+ const {receiver, args} = params;
+
+ const name = args[0].get('sym:player_name').value;
+ if (!converter.isStringOrBlock(name)) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_connect_game', 'statement');
+ converter.addTextInput(block, 'NAME', name, 'test');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'position_x', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isStringOrBlock(args[0])) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_position_coordinate', 'value');
+ converter.addTextInput(block, 'WHERE', args[0], '4:3');
+ converter.addField(block, 'COORDINATE', 'x');
+ return block;
+ });
+ converter.registerCallMethod(Koshien, 'position_y', 1, params => {
+ const {receiver, args} = params;
+
+ if (!converter.isStringOrBlock(args[0])) return null;
+
+ const block = converter.changeRubyExpressionBlock(receiver, 'koshien_position_coordinate', 'value');
+ converter.addTextInput(block, 'WHERE', args[0], '0:0');
+ converter.addField(block, 'COORDINATE', 'y');
+ return block;
+ });
+ }
+};
+export default KoshienConverter;