SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|
2025|01|

2025-01-04(Sat) 友人とのやりとりを自動化するXalebot-tmo

  先日、亀岡にドライブした夜に「AIとSF」というアンソロジを買って読み始めたのだが、その中の「没友」という作品には唸らされた。人とのやりとりをAIによる代理応答に任せることや、バーチャルに旅行することが当たり前になった時代。旧い友人とのやりとりの末、一緒にバーチャルな旅行に出かけたのだが、カフェで友人が語り出したエピソードから驚愕の事実を知る……という話。

  「没友」は「ぼっとも」と読むのだろう。「ボット」と掛けているわけだ。友人への返信を「ボット」に任せるなんて、なんとも失礼な話だが、メールでのやりとりに限れば、AIによる代理応答は既に実用域なんじゃないだろうか。仕事のどうでもいい相手からのメールなんて、AIに勝手に回答させておけばいい。ヘタすりゃ、こっちが死んでいても、相手は気づかずに給料は支払われ続けるかもね、などとカミさんと冗談交じりに話していた……のだが、ん? それって、別に冗談でもなんでもなく、既に実現可能なのでは? 先日に作ったXalebotを少し改造する程度で。名付けて「Xalebot-tmo」。「tmo」は「Thoughtless Mail Operator」の略。「ザレぼっとも」と読む。

  というわけで、取り組んでみたところ、改造というよりは、AIに与えるプロンプトとメール文面のカスタマイズ程度で済んでしまった。こんな感じ。

# 各プロンプト
@configs[:prompt] = {}
 
#configs[:prompt][:ex_q] = '以下の文章から、名乗りを含む挨拶部分、引用部分を除き、質問内容だけを抜き出してください。'
#configs[:prompt][:ex_a] = '以下の文章から、名乗りを含む挨拶部分、引用部分を除き、回答内容だけを抜き出してください。'
#configs[:prompt][:is_q] = '以下のような問い合わせがありました。'
#configs[:prompt][:is_d] = '以下の回答を行いました。'
#configs[:prompt][:mk_a] = 'それに対する回答案の作成を%sお願いします。'
 
@configs[:prompt][:ex_q] = '以下の文章から、引用部分を除き、内容をそのままの抜き出してください。'
@configs[:prompt][:ex_a] = '以下の文章から、引用部分を除き、内容をそのままの抜き出してください。'
@configs[:prompt][:is_q] = '以下のようなメールがありました。'
@configs[:prompt][:is_d] = '以下の返信を行いました。'
@configs[:prompt][:mk_a] = <<MK_A
それに対して返信内容の作成を%sお願いします。
なお、以下の例文に近い口調でお願いします。
「ふるたです。
 
はいはい、OKですよ。金曜ね。
 
ヤベシは休暇なのだよね。到着時刻はいつ?
時間によっては、自分がちょっと早退してもいいけど。
呑みは例によって、しげか月姫がいいな。
できることなら、カラオケは呑みより先にしたい。
 
ちなみに、金曜なら犬川くんは誘えばくるかもしれんが、
例のカラオケ問題があるから、ちと微妙かも。
 
ということで。
 
15時に抜けて、ホテルに迎えに行き、カラオケ2時間、
18時頃からしげで焼き鳥、締めはその辺でコーヒーって感じかな。
 
まー、彼の場合、たぶんそういうんじゃないんだよな。
 
15時始めだと、一緒に職場抜けるわけにもいかんし、まぁ、今回は誘うのはヤメとくか。
ヤベシがゴリゴリに押すなら考えなくもないけど。
 
宿は了解しました。そこ、歌のレッスンに行くときに通る道のすぐ脇だわ。」
MK_A

  最後、返信内容の作成指示がちょっと長いが、メールの文面を自分っぽくするために、過去に自分が返信した2通のメールの文面を渡しているからだ。今回は、適当に手動で見繕って固定的に与えているが、返信する相手によって、実際に過去に自分が返信したメールの文面を呼び出して渡すことも容易に実装できるだろう。

  で、ChatGPTの、今回は最新に近い「o1-preview-2024-09-12」を使って動作事例を作ってみた。それが以下である。

  画像の説明

矢部です。
 
7/29の10時〜7/30の12時半まで名古屋金山でお仕事でいます。
もしよろしければ、7/30の13時頃からあそびませんか?
遊べるようであれば、7/30の宿泊を取りますので早めにご連絡いただけると嬉しいです。
 
よろしくお願いします。

  名前は仮名の矢部くんにしてあるが、ほぼ実際に過去に友人から受け取ったメールである。で、自動生成された返信が以下。

ふるたです。
 
はいはい、OKですよ。7/30ね。
13時から遊べるとのこと、いいですね。ランチでもしながらゆっくり話そうか。
その後、もしよければカラオケでも行きます?できれば最初にカラオケ行きたい派なんだよね。
呑みは夜にでも、いつもの「しげ」か「月姫」がいいかな。
 
ところで、犬川くんも誘ってみる?でも例のカラオケ問題があるから、ちょっと微妙かもね。
まぁ、ヤベシが強く望むなら考えるけど。
 
宿泊の件、了解しました。早めに予約しておくと安心だね。
当日を楽しみにしてます。
 
ではでは。

  先に例示した文面に内容が引きずられすぎている傾向はあるが、意図はちゃんと消化されていて特段の矛盾はない。自分(オレ)から見ると文面のクセはちょっと違うが、数十行程度の例示でこの文面なんだからデキすぎレベルだろう。

矢部です。
 
返事ありがとうございます。
日曜日のホテルは伏見駅近く(ホテルハルミトンブラック)です。
なので、待ち合わせ場所は伏見駅近くがうれしいです。
待ち合わせ時間は13時頃を希望します。
お昼は各自済ませるか、一緒に食べるかどちらにしましょうか?

  さらに、ほぼ実際に過去に友人から受け取ったメールを返信してみる。で、自動生成された返信が以下。

ふるたです。
 
はいはい、OKですよ。7/30の13時、伏見駅ね。
宿も了解しました。ホテルハミルトンブラックか、あそこは場所的に便利だよね。
ランチは一緒にしましょうか。お腹も空くだろうし。
伏見の近くに美味しいパスタのお店があるんだ。そこに行ってみない?
その後は、カフェでゆっくりお茶でもしながら話そう。
 
そういえば、犬川くんも誘おうかと思ったけど、日曜は予定があるかもしれないし、今回は見送っておくよ。
ヤベシがぜひというなら連絡してみるけど。
久しぶりに会えるのを楽しみにしてるよ。
では、当日は13時に伏見駅で待ち合わせましょう。
 
よろしく!

  現実の自分(オレ)には「伏見の近くに美味しいパスタのお店」の心当たりはないが、返信内容としては特段の矛盾はない。よく見るとホテル名のタイプミスまで修正されている。これ、実際に友人の矢部くん(仮名)が受け取っても気づかないだろうな。

矢部です。
 
お昼を一緒に食べる件は了解しました。
私の方でも2,3見繕っておきます。
その後の予定はノープランなのでお任せします。
大須まで足伸ばすのもありかもしれませんが、暑そうなのでどうですかね。
夜の食事場所はフルタのお任せに甘えてもいいですか?

  さらに、ほぼ実際に過去に友人から受け取ったメールを返信してみる。で、自動生成された返信が以下。

ふるたです。
 
ヤベシ、お昼一緒に食べるの了解。
こっちでもいくつかお店をピックアップしておくよ。
 
午後はノープランとのことなので、涼める場所を考えておく。大須もいいけど、確かにこの暑さは厳しいかもね。
夜の食事場所は任せてくれてOK。良さそうな店を探しておくよ。
 
宿は伏見のハミルトンブラックね。そこ、よく通る道だよ。
じゃあ、当日は13時に伏見駅で待ち合わせで大丈夫かな?
 
当日、楽しみにしてるよ。

  ちょっと最後の確認が繰り返されているが、明確な確認がなされなかったからか? なんにせよ、許容範囲ではないかと思う。うーむ、実際に代理応答させていれば、約束をすっぽかすことになるが、代理応答としては完走してしまったと言えるんじゃないだろうか。

  これ、実際に友人に対して使うつもりはないけれど、こんな簡単な仕掛けであっても、相手側からすれば十分に自分(オレ)が存在しているように見えるわけで、それこそ、こっちが死んでいても気づくことは難しい。それって、ネット上に自分(オレ)が存在していると言っても、もはや過言ではないのではないか。

  今やSF的な「肉体を捨ててサイバースペースで生きる」という概念に新鮮さを感じることはないけれど、どうやって「精神をサイバースペースに転送するのか」という疑問に対しては、現実が先に結論を出してしまった気がする。つまり「AIに『クセ』を覚え込ませること」がそれなのだ。

  昔「ザ・フライ」という映画を観て「肉体の物質転送」が、実は「複製」と「削除」との2ステップで実装されていたならば、転送先の自分は「他人にとっては自分でも、自分にとっては他人ではないか?」という発想でSFを書いたことがあるのだが「肉体を捨ててサイバースペースで生きる」ってのも、なんだかそれに似たような薄ら寒さを感じるなぁ。


2025-01-02(Thu) ヴァリアブル・ジョイスティック「JS-2V」をさらに改良

  ホームセンタのバラ売りを買ったのだが、ケース内に長さの違うネジが混在しているのに気づかず、イザ締めようとした時に気づいてビックリ。1本はギリギリの長さだった。確認しなかったのは悪いが、ちゃんと元に戻しとけよな。まぁ、表面からは見えないからこれでよしとする。なんか、レイトレーシングCGっぽいな。ネジの頭にボールが映り込んでいるしw。

  画像の説明

  トラスネジは表面に頭が突出することを前提に、そこそこ美しさに配慮したタイプのネジだ。んが、実際の業務用の筐体では、内側のフレームにネジ止めするので、表面にはネジ頭が出ないのが正解なのだな。でもまぁ、自分のプレイスタイルでは、さほど邪魔になるわけでもないのでこれでよしとする。

  画像の説明

  一方で、裏のレバーの8/4方向の切り替えプレートを止めているネジを、手回し可能なものに交換した。実際に使ってみると想像以上に頻繁に切り替えが必要だったので。さほどガッチリと締め上げる必要のないネジなので、手回しで問題ないし。これはだいぶ大きな改良だな。

  ちなみに、トラスネジは28x4円。手回しネジは10本で128円。

  今回のアケコン製作の動機の大半はドルアーガだったのだが、なんかすっかり腕が落ちていてリハビリ中だ。老化するよりも早く杵柄を確立しなくては。ところで、複数の場所で見かけるのが「ドルアーガの上手い人はカッコいい」という記述だ。ドルアーガを知らない人がそう思う訳はないので、それなりにドルアーガをプレイしてきた人でそう思う人が多い、ということなのだろうが……ムッチャわかるんだよな、これ。何度か書いたが「起きうる理不尽気味な不運を咄嗟の状況判断で可能な限り抑え込んでいく」という、その奇跡のようなゲームバランスを知るからこそ、上手い人にリスペクトを感じてしまうのだ。宝箱の出し方の覚えゲー、という見方は側面のごく一部なのだ。ホント、1984年に出たとは思えない、始祖にしてオーパーツのようなゲームなんだよなぁ。


2024-12-31(Tue) 2024年の終わりに

  大晦日ということで、なにか総括しようかと思ったが、特には思い浮かばない。

  が、今年は、いわゆる「振り返り」をするクセが付いた気がする。週で、月で、年で。先日、安野貴博氏の講演を聴いて印象に残ったのが「振り返りはコスパがいい」だった。講演を聴く前からクセが付き始めていたので、妙に納得してしまった。「振り返り」自体は、当然「新たな取り組み」ではないけれど、それにより過去を評価でき、よりよい未来を選べる可能性が高まる。

  つうわけで、自分で今年のブログを見返してみると、欠かさずプログラミングしているなぁ。ジャンルは様々だ。よいなぁ。満足だ。小学6年から続けているから、42年弱。電子工作も、もう21年半になるのか。

  大きなドライブもしてるなぁ。まだまだ走りたい道はある。免許取ってから、34年チョイ。運転がイヤだった瞬間はない。ロードスターに乗り始めて丸7年。運転が楽しくなかった瞬間はない。

  ヴォーカルも進歩したなぁ。始めて6年チョイ。まだ伸びる気がするし、楽しく続けられている。

  ジョギング、筋トレも、始めて4年半。それほど苦もなく続いている。これ以上マッチョ度を増すつもりはないので、維持に努めているが、ちゃんと維持できている

  モデルガンは……一過性だったな。それなりに楽しかったけど、趣味としての発展性はないな。また、ヒマになったら手を出すかもしれんが。

  それと、41年前に出会った友人との旧交が復活したのは嬉しかったな。キャンプもなかなか楽しかった

  それにつけても、今年、特に感じたのは、本質を忘れた「団体」の多さだな。警察はだいぶ前からだが、耳目(クリックや視聴率)を集めることだけにフォーカスしてしまっているマスコミ。先日の航空機事故も含め、大概の事故は小銭をケチって当然の仕事(メンテナンス)を怠った結果、起きている。自分の所属している会社もそうだ。点稼ぎ主義。見ているのは客ではなく、上役や予算や数値になってしまっている。小銭の欲しさに客のトラブルを願うサポート部門って……控えめに言ってクソ以外の何物でもない。もう、あきらめた。が、トヨタだって、クルマの良さよりも、作りやすさやコストダウンにフォーカスして失敗した時期があるのだ。大会社だって普通に誤りうる。そもそも、日本国民の平均年齢は既に自分より下。歳と分別は必ずしも比例しないが、それでも若者ほどバカである傾向はあるだろう。自分もバカだった。

  それでも、別に何かができるわけではない。人は変えられない。自分が変わるほかない。

  さーて、来年は何をしようかなぁ。クソを眺めていたってイイ事はない。ウキウキできることは探せばあるはずだ。


2024-12-30(Mon) ヴァリアブル・ジョイスティック「JS-2V」を改良

  朝っぱらから、昨日作ったジョイスティックを修理してドルアーガしてみる。やはり4方向レバーはよいな。久々すぎて、宝の出し方があやふやになっているが、ふわふわっと19フロアまで。改めて挑戦しよう。

  ちなみに、4方向レバーが、どれくらい4方向レバーか調べてみた。昨日の「jstest-gtk」を使って、ゆっ〜くりとレバーを回す。すると、上半分は微妙にナナメに入る箇所があり、下半分は微妙にどちらにも入らない箇所があった。まぁ、機械的な制限であるから、パーフェクトはないんだが、十分に4方向している。すぐれものである。

  んが、やっぱり途中にタッパーを挟むのは、ものすごく使いづらい。両者をつなぐケーブルも短すぎた。というわけで、メイン基板の方に結線する形にして、ジョイスティック本体に一体化した。

  画像の説明

  アナログスティックは取り除いてしまおうと思ったが、ギリ高さが足りたので残してある。まぁ、こんな位置に付いていたって使いようがないけれど。

  しかし、やっぱりアケコンはいいなぁ。でも、今の若いもんには響かないんだろうなぁ。ゲームセンタの筐体にも、ゲームパッドがつながっているものがあったりするくらいだしなぁ。

  さて、自分の中で4方向レバーといえば、ドラゴンバスターなのだが、気がつけば大/魔界村やスパルタンXも4方向レバーなんだよな。なかなか新しい視点だなぁ。

  ちなみに、今回かかった費用。ジョイスティック3200円。ボール250円。ボタン400x3円。送料660円。MDFパネル178円。端材58円。あとは全部手元にあった道具と部品なので、合計5546円。


2024-12-29(Sun) ヴァリアブル・ジョイスティック「JS-2V」を製作

  さて、しばらく前にセイミツの業務用アーケードスペックのジョイスティックとボタンを購入したのだが、ガワの手配に悩んでいた。金属ではなく木材がいい。手が冷えるのはイヤだし、加工もラクなので。で、昨日、ホームセンタで材料を買ってきた。

  画像の説明

  手頃なサイズでフタ付きの木箱が欲しかったのだが、そんなに都合の良いものはなかった。しかたなく、手頃なサイズ、300x200のMDFパネルを天板にすることにし、足として端材をくっつけることにした。端材の幅は45。ジョイスティックのメカ部の格納には40チョイの高さが必要なので45はちょうどいい。178円と58円。仮組み用でも構わない値段だ。

  まずは足を付ける。端材の両端を150で落とし3分割。MDFパネルの裏に両面テープで位置決めして、皿タッピングで固定。寿司下駄ができあがった。元の端材の加工精度は高く、ほぼガタ付きはない。これ、普通にイケるなぁ。

  Φ29のホールソーでジョイスティックを取り付ける穴を空ける。ジョイスティックを固定する周囲のネジはΦ5。とりあえず適当なネジで固定したが、ここには後でステンのトラスネジを奢りたいな。

  自分の指の配置に合わせボタンを取り付ける穴を空ける。ここでもΦ29のホールソーを使うが、必要なのはΦ30。仕方ないのでヤスリとペーパで穴を拡げる。それなりに大変だったが、どうにか取り付けられた。思った以上にいい仕上がりだ。こういう工作も上達したなぁ。

  画像の説明

  次は乗っ取り工作。ちょうど表面が加水分解を起こして腐りかけていたゲームパッドがあったのでそれを使うことにする。BUFFALOのBSGP1601BKというもの。5年チョイ前に買ったもののようだが、なぜ買ったのか覚えていない。

  バラすと基板は2枚。面倒なことに、乗っ取りたい十字とトリガの接点は、メイン基板じゃない方にある。面倒くさいので、適当なタッパーの中に放り込んでUSBの配線をやり直しつつ、グラウンドを探し、十字と3つのトリガ、合わせて8本の線を引き出す。しかし、またもやパターン中には、各接点の途中にハンダを乗せられるパッドがある。乗っ取ってくれといわんばかり。なんなの、これ? 法律で決まっているの?

  画像の説明 画像の説明

  本体側に戻る。ピンヘッダで接続するために、それを固定する基板が必要なので、だいぶ前に作った基板を流用する。元はFT245AM用だが、もう使うことはないだろう。木材にタップを切ってネジで止める。そこからは空中配線。ヒドい手抜きっちゃー、手抜きだが、実際のアーケードゲームも、パネルを開けたらこんな感じになってるはずなので、気にしない。

  画像の説明

  さて、テスト、なのだが、Linuxの場合、コントロールパネルにジョイスティックの項目がない。が、dnfで探したら、ソレっぽいのがスグに見つかった。「jstest-gtk」と、そのものズバリだ。もちろん、動作はバッチグー。完成。やっほー。

  画像の説明

  4方向レバーを試すため、パックマンをプレイしてみる。うむ。良い感じである。続いて、3トリガを試すために、グラディウスII。4方向レバーではゲームにならないが、トリガの動作は良好。ならばヨシ。最後に、本命のドルアーガの塔……だが、下が効かない。よく見たら、コネクタが断線していた。今日はここまで。明日、直そう。

  久々に丸一日、楽しく工作することができた。が、老眼が進んでいるので、メガネの取り替えが面倒くさい。また、熱中して作業をしていると、固定した姿勢が続くのでちょっと筋肉がダルくなる。ここ数年、カラダはそれなりにガンガンと鍛えているのだが、固定した姿勢からのヨッコラセには効かないんだなぁ。歳には逆らえないなぁ。


2024-12-28(Sat) WebSocketクライアントを実装する

  しばらく前にMezatalkというチャットツールを作り、職場で活用している。チャットツールといえばWebSocketだ。発言の送信や受信には必須の機能である。通常、発言はブラウザのJavaScriptから行われる。が、Ruby版のコマンド「wsclient」も用意してある。ボットに発言させたい場合などに使える。こんな感じだ。

res = system('./wsclient',
	'ws://127.0.0.1:33109/',
	"{:REQUEST=>'login', :TYPE=>'talk', :USER=>'user1', :ROOM=>'_t~room1'}@@login",
	"{:REQUEST=>'sentence'}@@Hello.",
)

  実際、先日に記事にしたXalebotは、その名の通りボットであり、問い合わせに対する回答案などをMezatalkに発言するという連携機能も備わっている。

  で、今回「特定の発言が行われたら、別のシステムでその発言を処理する」という機能を実装する必要が生じた。まずは、別のシステムから発言を取得できるようなAPIを実装し、WebSocket経由で発言を取得できるようにした。さらに、発言が行われた場合に、設定ファイル中に記述した関数を呼び出す機能を実装し、そこから「wsclient」を実行しようとした、のだが……それが、どうやっても動かない。普通にコマンドとして実行すれば動くのだが、設定ファイル中からだと動かない。にっちもさっちもよっちもごっちも動かない。ドハマリ。

  「wsclient」は「em-websocket-client」というRubyのライブラリを使っているのだが、見よう見まねで書いたコードなので、それ以上に追求のしようがない。うーむ、こうなったら、独自に実装するか。

  というわけで、RFCの6455「The WebSocket Protocol」を眺めつつ、チマチマと実装していく。HTTPで接続後、プロトコルを切り替えたり、クライアントからの送信内容にはマスクを施したり、なんかいろいろと珍しい処理がある。面倒クサいが面白い。面白いが面倒クサい。

  そしてデキたのがコチラです。

#!/usr/bin/env ruby
 
require './wshelper'
require 'timeout'
require 'socket'
 
wsh = WebSocketHelper.new(uri = ARGV.shift)
 
Timeout.timeout(3) {
    sock = TCPSocket.open(wsh.uri.host, wsh.uri.port)
    sock.syswrite(wsh.handshake)
    sock.sysread(9999)
 
    while(request = ARGV.shift)
        sock.syswrite(wsh.encode(request))
        puts('[%s]' % wsh.decode(sock.sysread(9999)))
    end
    puts('Closed.')
}
require 'uri'
 
class WebSocketHelper
 
    attr_reader :uri
 
    def initialize(uri)
        @uri = URI.parse(uri)
    end
 
    def handshake
        (<<REQ % [@uri.path, @uri.host, @uri.port, make_websocket_key]).gsub(/\n/, "\r\n")
GET %s HTTP/1.1
Host: %s:%s
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Key: %s
Sec-WebSocket-Version: 13
 
REQ
    end
 
    def make_websocket_key
        nonce = []; 4.times { nonce << rand(0xFFFFFFFF) }
        @websocket_key = [nonce.pack('N*')].pack('m0')
    end
 
    def encode(req)
        make_masking_key
        head(req) + payload(req)
    end
 
    def make_masking_key
        @masking_key = rand(0xFFFFFFFF)
    end
 
    def head(req)
        head = ''
 
        fopc = 0
        fopc += (fin = 1) << 7
        fopc += (opcode = 1)
        head << [fopc].pack('C')
 
        mplen = 0
        mplen += (mask = 1) << 7
        if((it = req.length) < 126)
            mplen += it
            head << [mplen].pack('C')
        elsif(it < 65536)
            mplen += 126
            head << [mplen, it].pack('Cn')
        else
            mplen += 127
            head << [mplen, 0, it].pack('CNN')
        end
 
        if(mask == 1)
            head << [@masking_key].pack('N')
        end
 
        head
    end
 
    def payload(req0)
        len0 = req0.length; req = req0.dup
        req << "\x00" while(req.length % 4 != 0)
        res = []; req.unpack('N*').each {|u32|
            res << (u32 ^ @masking_key)
        }
        res.pack('N*')[0, len0]
    end
 
    def decode(res)
        fopc = res.slice!(0, 1)
        mplen = res.slice!(0, 1).unpack('C')[0]
        if(mplen < 126 and mplen == res.length)
        elsif(mplen == 126 and (res.slice!(0, 2).unpack('n')[0]) == res.length)
        elsif(mplen == 127 and (res.slice!(0, 8).unpack('NN')[1]) == res.length)
        else
            raise('Unexpected.')
        end
        res
    end
end

  まぁ、ヤルことちゃんとヤッてない。んが、仕事はキッチリこなします。まるで、オレみたいなヤツだな。んが、やっぱり、設定ファイル中から呼ぶと動かない。にっちもさっちもよっちもごっちも動かない。な、なんでぇ?

  終いにはtcpdumpでパケットまで確認してしまう。要求は出ている。んが、応答が返らない。設定ファイル中から呼んだ場合だけ。なんだこれ。いや、正確にはタイムアウトした瞬間に応答が返る。なんだこれ。なんだこれ。なんだこれ。サーバ側の問題?

  サーバ側は「em-websocket」というRubyのライブラリを使っているのだが、見よう見まねで書いたコードなので、それ以上に追求のしようがない。うーむ、こうなったら、独自に実装するか……って、イヤ、それはオオゴトすぎるべ。さすがに、これまで4年近くも動いているコアの部分はイジるべきではないだろう。

  そこでようやく気がついた。サーバ側に追加した、このコード。

it = @configs[:post_paragraph_hook] and it.call(room)

  これ、connection.onmessageの延長、つまり、コールバック関数の中で動いている。そんなトコで、さらに「wsclient」で要求を出して応答を待ったって、サーバ側もそこで待っとるっちゅーねん。つまり、要求を処理するヤツが、要求を出して応答を待ってたって、応答するヤツはテメエ自身なんだから、応答が返るわけがない。ぷふゎぁ〜……。

  長らくプログラミングしているが、こんな状況は初めてだなぁ。じゃ、どうすりゃいいか。こうすりゃいいだけだ。

it = @configs[:post_paragraph_hook] and Thread.new {
    it.call(room)
}

  ちゅーわけで、動くようになった。結局、元の「wsclient」が使えたので、WebSocketクライアントの独自実装は徒労に終わった。でも、結果として目的は達成できた。結果オーライ。

  けどね。エンジニアの諸君には言うまでもないだろうが、技術力というのは膨大な徒労によって培われるものなのだ。見える成果だけを成果とするならば、それは当たり馬券以外には金を払わない、と主張するのと同じ。

  しかし、久々に悩ませられたなぁ。そのぶん、動いたときの嬉しさは大きかった。これだからプログラミングは、やめられまへんなぁ。


2024-12-20(Fri) ヴァリアブル・ジョイスティック「JS-2V」製作開始

  先日、なんの気なしに共立「シリコンハウス」に行ったのだが、アーケードゲーム用のジョイスティックとボタンをみかけ、また作りたくなってしまった。だいぶ以前にそれなりのものを作ったのだが、あれは8方向レバー固定なのだ。4方向レバーに変更できる仕様のものがほしい。

  品揃えは千石がよいようだが、いまひとつ仕様がハッキリしない。セイミツのオフィシャルサイトと見比べながら、どうにかモノを選定した。ジョイスティックはLS-32のSEベースというもの。もっともオーソドックスな仕様だということで選んだ。

  画像の説明 画像の説明

  裏側には複雑に穴の空いたプレートが装着されており、装着する場所をズラすことにより、レバーの動きを8方向、4方向、2方向に物理的に制限することができる。ちょっとテスタで調べた限りだが、4方向モードでは、絶妙に斜めに入らないようになっている。つまり、縦と横のスイッチが同時にONにならないのだ。まさに欲しかった仕様だ。

  欲を言えば、パネルを外しても8方向レバーを回すと引っかかりがあるのが残念。滑らかにレバーを回すことはできない。そういうプレートも別売されているかもしれないが。とりあえず残りの人生でザンギエフを使いだすことはないと思うので、大丈夫。あ、バルトリックには有用かな。

  ついでにレバーボールとボタンも買った。ボールはLB-35というもの。35φで黄色。オイラの軸足はナムコだからね。ボタンはPS-14-GNというもの。例によって3つ。グラディウスはやりたいが、格ゲーはやらないので。30φで黄色。オイラの軸足はナムコだからね。

  以前のヤツは最終的にだいぶゴチャゴチャした感じになったが、今回はUSB対応だけでいいかな。おあつらえむきの木箱を探さなければ。


2024-12-19(Thu) Fedora41でrakipicしてsdccする

  先日、なんの気なしに共立「シリコンハウス」に行ったのだが、久々にハンダゴテを振るいたくなった。チギれていたテスタのICクリップを付け直し、PICの開発環境を整え始める。ここ数年やってなかったしな。今でも似たような手順で整えられるものだろうか。

  画像の説明

  いまのFedora41の前、Fedora30の時も一応は整えていたようだが、記事としてはもうひとつ前のFedora24だな。まずは、rakipicで、秋月のPICライタの健康チェックをしてみる。

raven.itline.jp: /root/rakipic # git clone http://itline.jp/git/rakipic
raven.itline.jp: /root/rakipic # cd rakipic
raven.itline.jp: /root/rakipic # ./install

  部品箱をゴソゴソして、使い古しの16F648Aを見つける。PICライタにセットして読んでみる。

raven.itline.jp: /root/rakipic # rakipic -p 16F648A -r

  なんか息継ぎするな。最後まで行かずに止まってしまうし。

raven.itline.jp: /root/rakipic # rakipic -p 12F629 -r

  8ピンPICは大丈夫だ。

raven.itline.jp: /root/rakipic # rakipic -p 16F648A -r

  別の個体なら大丈夫だった。そんなことあんのか?

raven.itline.jp: /root/rakipic # rakipic -p 16F819 -r

  こっちもOK。今でも型番は忘れていないな。16F688も試したかったが、治具が見当たらず。捨てはしないが、どこにしまい込んだのだろう。

  次はコンパイラ環境。まずは、ワザと失敗させる。

raven.itline.jp: /root/rakipic # make all
sdcc-sdcc -V --use-non-free -mpic14 -p16f648a -c blink_led_16f648a.c
make: sdcc-sdcc: そのようなファイルやディレクトリはありません

  アセンブラとコンパイラを導入。んが、ヘッダファイルが足りない。

raven.itline.jp: /root/rakipic # dnf install gputils
raven.itline.jp: /root/rakipic # dnf install sdcc
raven.itline.jp: /root/rakipic # make all
blink_led_16f648a.c:2:123: fatal error: pic16f648a.h: No such file or directory

  例の、フリー、非フリー問題か。非フリーのスイッチを落とし、パッケージを再ビルドする。

raven.itline.jp: /root # dnf download --source sdcc
raven.itline.jp: /root # rpm -ivh sdcc-4.1.0-11.fc41.src.rpm 
 
raven.itline.jp: /root # vi rpmbuild/SPECS/sdcc.spec 
raven.itline.jp: /root # diff rpmbuild/SPECS/sdcc.spec.org rpmbuild/SPECS/sdcc.spec
< %configure --enable-doc --disable-non-free  STRIP=: ${OPTS} PYTHON=python3
> %configure --enable-doc STRIP=: ${OPTS} PYTHON=python3
 
raven.itline.jp: /root # dnf install bison boost-devel flex latex2html lyx texinfo inkscape
raven.itline.jp: /root # rpmbuild -ba ~/rpmbuild/SPECS/sdcc.spec 
 
raven.itline.jp: /root # rpm -ivh ~/rpmbuild/RPMS/x86_64/sdcc-4.1.0-11.fc41.x86_64.rpm 

  再ビルドに1時間くらいかかったが、とりあえず前と似たような手順で導入できた。例によって、ヘッダファイルの調整が必要だったが、なんとか16F648AでLチカに成功した。

  画像の説明

  しかし、久々に秋月のサイトでPICを見て驚いた。軒並み値上げしている。こんなに高かったっけ? 16F688については、以前の日記に「120円という価格が魅力だ」って書いてあったが、それが330円だとは。まぁ、便利で高機能なチップなのだから値段相応と言われればそんな気もするが。こないだの半導体不足とも関係あるのかしらん。個人的にはだいぶ買い貯めてあるので、死ぬまで買わずに済みそうな気もするが、ちょっとPICを見る目が変わってしまったな。

  さてさて、特段、必要に迫られているわけではないが、リハビリのために照度/温湿度計でも作ってみようかしらん。


2024-12-17(Tue) なんとなく大阪へ走り出す

  6時に目を覚ます。朝食は6時45分から。ここんとこロングドライブの宿は、開店と同時がデフォだ。パパッと食べて駐車場に向かう途中、フロントガラスをガリガリしている人を見かける。え。そんなことになってんの? と、思ったら、なってた。ガリガリするの面倒なので、エンジンをかけデフロスタをマックスにして待つ。まぁまぁ溶けたら出発。でも、幌は凍りついているので開けられない。残念。

  画像の説明

  今日は大阪に行ってみることにした。ちょっと前に計画した「パークアンドライド」を試してみようかと。目的地は日本橋付近。だいぶ前に行ったレトロゲーセン「ザリガニ」と、共立「シリコンハウス」でも再訪するつもりだ。

  山道を門真市に向かって南下する。雪が心配だったが大丈夫。酷道かと思ったら、そこそこ交通量があり、連なって走ることに。が、その先、市街地に入るとかなりの渋滞だ。なぜか茨木駅前を通過。摂津の新幹線基地の横を通り、なんとか門真市へ。

  知ってはいたが、駐車料金は平日なので550円ではなく990円。ガード下なので無闇に狭く、あまり快適とは言えない。門真市から京阪電車で北浜へ。280円。大阪の電車ってなんか違うな。北浜での乗り換えは地下で完結。案内が多く迷わない。堺筋線に乗り換えて恵美須町へ。240円。んが、恵美須町駅を上がった交差点にある駐車場が、当日800円、休日でも1800円だと!? なんやそれ。パークアンドライドの意味ないやんけw。まぁ、市内の渋滞は避けられるし、電車も楽しいけど、別に必要なかったんかいな。あほらしわぁ。

  気を取り直して、レトロゲーセン「ザリガニ」へ。なんだか活気がない。そりゃ、平日だからな……と、いうのともなんか違う印象。いきなりテトリスが目を引く。画面の色ズレで四角の黄色ブロックが3x2みたいに見える。これはキツそう(笑)。アフターバーナーが3台並んでいるのはスゴいよな。アウトランもダライアスもある……けど……あれ? アウトラン、なんだか画面がスクエアだ。ちょっと笑えない。

  画像の説明 画像の説明

  やっぱりダライアスはやっておくべきだよな……が、1P側のコンパネが使えないので2P側でプレイしろという状態。海外版ならではの逃げ方だな。まぁ、右側にいること多いんだし、いいか。ボタンが連射付きなのはいいが、連射なしボタンはなし。コインも入りづらい。うーん、呑み込まれないだろうなぁ……入った。あれ、中央のモニタの色がヘンだ……んー、なんだか? なんだか??

  プレイを始めてすぐにレバーの反力がユルいことに気づく。ユルいどころか、時々、下に入りっぱなしになる。実はこの症状、ダライアスの純正レバーにありがち。だから、前回来た時はシャキッとした反力に、むしろ驚いたんたものだが……これは狭いステージに行くのが怖い。エキストラバージョンではないようなので、ミサイルで止める。なんとなく、保険を多めに5つで止めた……ところで、中央のモニタの色がヘンなのは、赤成分が抜けているから、ということに気づく。これだとカプセルの色がわからん。赤かと思うと取るのを躊躇してしまう。

  「A-C-F-J-O」と下ルートを進む。青をいくつか逃したので、いまだスーパーアームのまま。ほんじゃ、と、Tを抜けて、Yに進んだ。狭いトコは無事に抜けられたが、イカの直前でアームが剥がれた。これはキツい。正面切って戦うほど若くはないので、上の腕に張り付くが、痛恨のミス。正面でも戦ってみるが、ヤズカがキツい。すべての残機を潰し終了。まぁ、そんなもんか。

  2Fに上がってみたが、サイバリオンもドルアーガも動いていない。と、ようやくそこで、疑念が確信に変わった。きっと、飽きちゃったんだなぁ、これ。動いていない筐体が端に固められている。どれも、稼働するに満たない状態なのだろう。メンテナンスを怠ると、こういうことになるんだなぁ。

  画像の説明

  レトロゲーセンって、全国に数えるほどしかなくなってきてるけど、その各々は想像以上の情熱によって支えられていたのだ、ということを実感させられた。ゲームセンタなんて、基本は個人が営利のために運営しているわけだから、その運営状態は運営している個人の裁量に依存する。ある意味で「底」を見ることができて、当たり前のことに気付かされた。まぁ、自分もレトロゲーは好きだけど、飽きずに何年もメンテし続けられるかといわれると必ずしも自信ない。

  対象がパブリックになっていると誤解しがちだが、法に反しない範囲で次第に腐っていっても、法は止めてはくれないのだ。それは大きな会社だろうが同じ。個人経営はもちろん、イエスマンに囲まれている経営者は、方向性を誤ってもそれに気づけない可能性が高いだろう。もっと大きく、業界だろうが、国家機関だろうが、それは起こりうる。それを個人の働きかけで変えることは難しい。できるのは、それを正しく捉えて振る舞うことくらい。たった100円で多くのことに気づくことができたな。さらばザリガニ。これが最後だ。二度とここには帰らん。

  次の目的地である共立「シリコンハウス」へ。最近、ハンダゴテを振るってないので、そんなにワクワクしないし、買うものもない。そういえば、マウスのセンタークリックが腐りかけてたことを思い出し、タクトスイッチだけ買っておく。33円。6個で198円。と、その近くでアーケードゲーム用のジョイスティックとボタンをみかける。ちょっとイイな。でも、4方向レバーに変更できるヤツが欲しいんだよな。帰ったら探してみよう。やっぱり、実店舗はインスピレーションを与えてくれて、イイ。

  さて昼飯時だが、お好み焼きや、たこ焼きや、串かつは、どうにも気が進まない。寒いこともあり、見かけた喜多方ラーメン坂内で済ませた。大阪に来た意味ないなぁ。せめて、それっぽい場所を見て回ろう、と、道頓堀を抜けて、淀屋橋まで歩く……が、さすがにちょっと歩き過ぎてつかれた。さほど得るものもないし。京阪急行で門真市のクルマに戻る。期待はしなかったが、manacaだったので、やはりパークアンドライド割引はなし。ちぇ。

  画像の説明

  門真市からは知った道だ。最近やたらと寄る道の駅「お茶の京都みなみやましろ村」で休憩。名阪国道。伊賀ICで下りて旧25号。あとはいつもの道。19時着。

  旅はいいな。必ず収穫がある。まぁ、旅には限らないけれども。


2024-12-16(Mon) なんとなく亀岡へ走り出す

  いろいろな意味で遂に仕事に見切りをつけてしまったので、少し休むことにした。丸々一週間。理由は、充電でも、自分探しでも、仕事探しでも、有給消化でも、メンタル不調でもよいが、有給に理由はいらないのだよな。特段の理由はないが、あえて言うなら「時間を食べるテスト」だろうか。

  そのテストならば、ずっと家にいる方がよいような気もするが、せっかくならロードスターの相手もしたい。なんとなく、嵯峨嵐山のトロッコ列車を思い出し、行ってみることにした。今回はあえてユルい計画で行く。決めたのは亀岡の駅前の宿だけ。トロッコ列車に乗るかどうかも気分次第。

  ユルい気分が過ぎたのか、カメラも布チェーンも忘れてしまう。ある意味で計画通りか? 23号から421号へ、石榑トンネルを抜け、昼時になったので、道の駅「奥永源寺渓流の里」へ。鹿カレーというのを見つけたので食う。意外と肉が多くて得した気分。

  平日なので市街地は常に渋滞気味だ。近江大橋を通り、山中越で京都市街へ。っと、そこで左から目の前に車が飛び出し、ABSが作動するほどのハードブレーキ。こっちは見ていたので、まだ余裕はあったが、1秒先を走っていたら避けられなかったかも。アホタレが。

  金閣寺の横を抜け、道を間違えて清滝トンネルへ。福井のトンネル群みたいな信号があったので、先が行き止まりと知りつつ長らく待って通ってみたが、やはり廃線トンネルの転用らしい。戻りは上の峠を通ったが、恐ろしく凸な道路をメクラで通らされた。後で見たら上にミラーがあったらしい。そんなの気づかんて。その後、そこそこヤバげな道を抜け、保津峡駅へ。

  画像の説明 画像の説明

  特段、なにがあるわけでもない。トイレを済ませて北へ。ここから西、亀岡方面へは、線路はあるが道路はないので、かなりの大回りが必要なのだ。引き続き、そこそこヤバげな道が続くが、いきなり集落が現れる。水尾という町らしいが、スゴい場所もあったもんだ。さらに先に進むと、路肩に雪が現れ始める。ちょっと焦ったが、どうにか北へ抜けた。

  田舎道を南下し亀岡へ。デカいサッカースタジアムがあり、駅周りだけ都会のふりをしているヘンテコなトコだ。駐車場は24時間で250円。とりあえず、ホテルにチェックインし、夜の散歩に出る。

  特段の当てはないが、SFでも読みたい気分なので本屋へ。文庫を作者名順に並べるのはヤメろよ、と思った矢先、ハヤカワ文庫が平積みされているのを見つけた。珍しいこともあるもんだ。「AIとSF」というアンソロジを見つける。安野貴博、野崎まど、野尻抱介と並んだら買うしかない。ちょっと高いがレジへ。新品の紙の本を買うのはしばらくぶりだ。にしても、ちょっと厚すぎないか。

  ホテルのレストランで晩飯。枝豆、熱燗、豚の生姜焼き定食、大盛。風呂はまぁまぁ。ベットで読書。で、野崎まどの作品に爆笑。AIって、SFって枠で捉えると、どうしても悲観的になりがちだけれど、未熟なAIの感覚のズレを楽しもうってのは、発想が好き。SF要素は後付けっぽいけど。

  さて、明日は何をしようか。とりあえず、早く起きるために、早く寝ることにしょう。