掛け算の筆算について

2桁同士掛け算の筆算って、こんな感じじゃないですか。画像検索して確認したけど、教え方は昔と変わってないと思います。


この56×78の例で言うと、56×8=448と56×7=392を求めてからそれぞれの和を求める。
で、繰り上がりをこのように小さくメモしているのが良くないと思っていて、たとえば6×8の繰り上がりであるこの小さい4は5×8=40に吸収されて44になった時点で用済みだから、消えてなきゃいけないと思うんですよね。

なので、繰り上がりの処理は一旦後回しにして、繰り上がる数と繰り上がられる数両方をメモ的な状態にしておいて

この状態から足し算するほうがミス少なくなると思いませんか?

ゲームパッドの決定ボタン・キャンセルボタンの位置問題について

結論

最初に結論から書きますが、「×に"決定"の意味があるからPSが原因」ではなく「GENESISのAB(C)ボタンの配置が原因」だと思います。

「なぜ海外でこうなったのか」の話でGENESISの存在を無視する意味がわからない。
ゲームコントローラーの戦犯はSONYじゃない

決定・キャンセルボタンについての認識

まずこの問題は洋ゲーが日本に多く流入するようになったことで取り沙汰される様になった問題です。
我々日本のゲーマーはファミコンスーファミ→プレステを経由してきてから洋ゲーに触れた勢が多いと思われます。
これらのハードの邦ゲーでは「右が決定ボタン・左(下)がキャンセルボタン」が多く、洋ゲーで採用されている「下が決定ボタン・右がキャンセルボタン」という配置に面食らいました。
洋ゲーが本邦でも多数リリースされたXboxに対して「XboxがAとBの配置をスーファミと逆にしたせいでこんな混乱が起きた」との説が流れ、それに対して「PSの×ボタンに英語圏では"決定"の意味があるからこうなった」という説が発生し、今では「×ボタン起源説」が有力な状態となっていると思われます。

×が"決定"って本当?

あの説では正しくは「×」は「決定」とは言っておらず、「×」は「チェック」ということから「×ボタン」が「決定」にアサインされたという説です。でも「チェック」と「決定」は違うんじゃないの?と。
その辺の話で古い記事で2003年のものを見つけましたが、×が決定とは言ってないんですよね。これ以降で「×に決定の意味がある」的なことを言い切ってるのはある。
ABボタン論 - AYS:
「○」ボタンはキャンセル!? 日本と海外で変わる記号の意味 | A.C.O. Journal | A.C.O. Inc.


英語圏 チェックマーク - Google 検索

□の中に×や✓で「選択」を意味するのは間違いないようですが、「OK」「キャンセル」の二択なら「✓」と「×」が逆の意味を持ち、「×」が「キャンセル」の意味を持ってるっぽいですよ。
それに加えてON/OFFスイッチに描かれた「O」と「I」では「O」が「OFF」の意味だから、「×:決定・○:キャンセル」になったってツギハギすぎませんか?
チェック・未チェックの組み合わせで☒と□があるんだから、「×:決定・□:キャンセル」でも良かったじゃんって思うんですが。

PSの×ボタンが起源とするのは、ファミコンスーファミ→プレステと辿ってきた流れの先から過去を振り返ろうとした場合の限界であり、洋ゲーが辿った歴史を無視してるんじゃないのかなと思うわけです。

2ボタン時代

ファミコンPCエンジンマスターシステムのコントローラーはそれぞれこうなっています。
A,B,1,2いずれにも「決定」「キャンセル」の意味はありませんが、マスターシステムの1ボタンはSTARTと書かれており、決定ボタンをアサインする意図が見えます。

ファミコンソフトの取説として、ファミコンミニのサイトをリンクしておきます。FF3で「Bキャンセル・A決定」になっていることがわかります(ボタン配置順)。
ニンテンドークラシックミニ ファミリーコンピュータ 説明書 | 任天堂


PCエンジンPCエンジンミニのサイトをリンクしておきます。こちらは邪聖剣ネクロマンサーで「2キャンセル・1決定」であることが確認できます(ボタン配置順)。
PCエンジン mini


マスターシステムはいいのが見つからなかったのでメガドラミニで勘弁してください。シャイニングフォースで「A決定・Bキャンセル・C決定」であることが確認できます(ボタン配置順)。
メガドライブミニ | セガ

以上のことから、8bit機時代から配置ではなくボタン名が若い方から順に「決定・キャンセル」をアサインしていたという歴史があることがうかがえます。
Xboxがボタン名を逆にしたから説」に対して「Aに決定なんて意味ないだろ」と思いましたが、歴史的には「Aに決定をアサインするべき」のような指針はあったわけです。
また、ボタンを左から順に並べたのはMSではなくセガです。

結論

つまり、セガハードのボタン配置に準拠していたら左(下)のボタンが決定になりがちです(Aや1を「決定」にアサインするという不文律を無視すれば別)。
日本ではメガドライブはそんなに売れていませんが、海外ではGENESISはメチャクチャ売れました。そのせいで、GENESISの仕様がデファクトスタンダードとして普及したんでしょう。
もしPSがスーファミと同じボタン名・ボタン配置だったらどうなったかわかりませんが、「PSのパッドがどうとでも解釈できるボタン名」だったのが災いしてデファクトスタンダードであるセガ側に寄せてしまったこと、Xboxセガ派のボタン配置だったことから海外では完全に「下決定」が主流になってしまったと考えます。

Screeps:Arena チュートリアルだけやりました(デモ版ではなくちゃんと買ったのにまだそれしかしてない)

先日早期アクセスでリリースされたこのようなゲームがあるとのことで早速飛びついた news.denfaminicogamer.jp

多少趣が違うScreeps:Worldという前作(?)があるようだけど、軽くググっただけではWorldについての日本語記事も見つけられなかったので、Arenaの方のチュートリアル完了までのことを少し日本語で書いておきます。(だいたいで書くので、正確なことはゲーム内のリファレンスとかを頑張って読んでください)

ゲーム概要

生産施設、エネルギー資源、ロボ(クリープ)なんかが配置された空間があり、

  • 生産施設はクリープを生産
  • 作業クリープはエネルギーを収穫
  • 攻撃クリープは敵が近くに居たら攻撃、射程外なら接近する

プレイヤーは上記のようなことをさせるプログラムを読み込ませて、敵プレイヤーと結果で争います。

試合の目的は、今のところ「フラグを取る」「敵の生産施設を破壊する」「点数を稼ぐ」の3種類あるようで、それぞれ入り口が別なので、目的に応じたプログラムを組むことになります。

前述の記事で「リアルタイムストラテジー」と表現されていますが、プレイヤーは「AIの行動をプログラミングしたソースコードを読み込ませる」「結果を見る」をやるだけで、リアルタイムで操作することはないです。なのでRTSではないんじゃないかなー、と。最初に記事を読んだときは「ムム!左から敵が!!戦力を左に集中!!カタカタカタカタ…ッターン!!」みたいな感じかと思ったんですけど違うようです。

※これ書いた後に一回試しに対戦してみっかと思ったんだけど、対戦相手探し中のまま何分も待たされてるので「アップロード済みのソースコード同士で非同期に対戦が開始される」わけではないっぽい

チュートリアル解説

チュートリアル2~9は画面下部の「Sample Code」にクリアに必要なコードが用意されている(1は本文中にある)ので、それをコピペすれば9まではクリアするだけならできます。

注意点としては、1面でスクリプトの置き場所が「C:\Users[username]\ScreepsArena\tutorial-loop_and_import」となっているのを、例えばDドライブなどに変更したとしても、2面を開くと一旦「C:\Users[username]\ScreepsArena\tutorial-simple_move」にデフォルトのファイルが作られるので、Dドライブに先回りしてファイルを作って「なんで動かないんだ?」となる可能性があるんじゃないかと思います(しばらくそれで悩んだ)

1.Loop and Import
メインループ

試合中、1ターンごとにメイン関数から loop() 関数を呼ばれます。この loop() の中で処理がループするわけではないので、たとえばこの関数の先頭で変数の初期化などを行う場合、毎ターンそれを実行することになるはずです。「1ターン目だけ実行したい」場合は getTicks() == 1 で判定するなどの工夫が必要になります。

また、関数の外にグローバル変数を宣言し、ターンを跨いで値を持ち越すことは可能です。

インポートの書き方

import { getTicks } from '/game/utils';

何がインポートできるかなどは後のチュートリアルでも出てくるのでとりあえずサンプルコードコピペでいいと思います。

2.Simple move
クリープやフラッグ、その他オブジェクトの取得

getObjectsByPrototype() で、オブジェクトタイプを指定することで、フィールド内のそのタイプのオブジェクトの配列が取得できます。1個の場合でもちゃんと配列になります。

味方のクリープ+敵のクリープ、味方のフラッグ+敵のフラッグなど、敵味方ごちゃまぜで取得されるので、味方のオブジェクトに絞り込みたい場合はチュートリアル3で出る方法を参照してください。

クリープの移動

creep.moveTo(target); targetのオブジェクトに向けて1歩移動します(最短経路かどうか怪しい動きをする時がある気がする)。多分座標指定とかもできると思うけど調べてないのでリファレンス見てください。

チュートリアル4で出てきますが、クリープは「MOVE」や「ATTACK」など、可能な行動を示すパーツを装備しています。この章では触れていませんが「MOVE」がないと移動できません。

3.First attack
味方クリープの抽出

var myCreep = getObjectsByPrototype(Creep).find(creep => creep.my);

まあ、 find はJSの普通の関数ですね。他の条件で絞り込みたい場合は他の条件で絞ると良いと思います。

クリープの攻撃

「ATTACK」を持っているクリープは隣接した敵を攻撃することができる

if(myCreep.attack(enemyCreep) == ERR_NOT_IN_RANGE) {
    myCreep.moveTo(enemyCreep);
}

「攻撃できたら行動終了、攻撃が届かないなら移動」という感じで、このゲーム用の書き方かなと思います。

attackとmoveを同じターンのうちに両方行っても特にエラーにはならないようです(attackを無限ループしたら勝ちじゃんと思うけど、多分1つのオブジェクトは同じ行動は1ターン1回しかできない)

4.Creeps bodies
クリープのパーツの種類

まあ名前を見ればわかると思いますが、以下の種類のパーツがあり、装備しているパーツに応じた行動が可能です。 - MOVE:移動ができる - ATTACK:隣接したクリープを攻撃できる - RANGED_ATTACK:3マス離れたクリープを攻撃できる - HEAL:自分自身か他のクリープを回復できる - WORK:エネルギー源からの収穫、建設、建築物の解体 ができる - CARRY:運搬ができる(エネルギーの収穫をさせたい場合、WORK+CARRYにしないと多分持てない) - TOUGH : HPが多い

たとえばチュートリアル3では「MOVE」「ATTACK」を持ったクリープが用意されていました。

これらは敵の攻撃などで個別に破壊されることがあります。「MOVE」だけ破壊されると固定砲台のような状態でその場に残りますし、「ATTACK」だけ破壊されると移動だけできる状態で生き残ります。どの順で攻撃・破壊されるかは調べてないです。

5.Store and transfer
タワー

エネルギーが10あると攻撃できる。チュートリアルでの出番がこれだけだったから調べてない。他はリファレンス参照

エネルギーの受け渡し
  • transfer:クリープから他のものに運搬中のエネルギーを渡す。CARRYを持つクリープ同士での受け渡しも可能
  • withdraw: 他のものからエネルギーを取得する。リファレンスを見るとクリープからも取れそうなんだけどうまくいかなかった。
6.Terrain
地形

超えられないブロックがあるので、 findClosestByPath() を使うことで「到達可能な最短経路があるオブジェクト」を見つけることができる。 findClosestByRange() だと「到達不可能でも最も距離が近いオブジェクト」を見つける。

7.Spawn Creeps
クリープの生産

スポーンが設置されている場合、スポーンに指示することでクリープが生産できる。

前述のクリープのパーツを複数指定(同じ属性を複数指定することも可能っぽい)して生産できる。パーツごとに必要なエネルギー量が違う。

1つのスポーンで1ターンのうちに1体しかクリープを生産できない(2体生産しようとすると1体目もうまく生産されず詰むと思う)ことと、生産されたクリープはそのターン中は何もできないことに注意。

8.Harvest energy
エネルギーの収穫

WORKとCARRYを持ったクリープは、harvest() でエネルギー源からエネルギーを収穫して保持することができる。

9.Construction
建築

WORKを持ったクリープはタワーを建築できる(エネルギーが要るので実質的にはCARRYも必要)。

createConstructionSite() で建築場所を設置して build() で建築。 createConstructionSite() したターンは build() できないかも(未確認)

10.Final test
  • クリープの生産
  • エネルギーの収穫と運搬
  • 敵の攻撃

と、チュートリアルでやったことを組み合わせることになる。 開始時点では、敵は壁に囲まれたエリアにいて攻撃できないが、壁を破壊して出てきてくれるので、その後で倒せばOK。 (こちらも壁の破壊に協力すれば早く出てきてくれると思うが、壁の攻撃の指定などが面倒で試してない)