C64 バージョンのバシック言語ダンジョンクローラー:ゴブリン襲撃(C64 バージョンの一部8)

2026/07/20 0:20

C64 バージョンのバシック言語ダンジョンクローラー:ゴブリン襲撃(C64 バージョンの一部8)

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

パートエイトは、このコモーダ BASIC ゲームにとって決定的な進化を意味し、核心的な安定性の問題を取り除き、コアエンジンをアップグレードする。最も重要な変更は、静的な敵を、平行アレイ(GH(10)、GX(10)、GY(10))を用いてプレイヤーを追跡しながら、健康状態と位置を追跡し、メモリー腐敗を回避する知的ゴブリンに置き換えることであり、これは以前のプロトタイプで発生した主要なバグであるアレイの成長が 4K の文字セットと衝突するという問題に対処するためのものである。厳格な 16K メモリ制約および可変切断の問題に対処するために、この更新では BASIC キーワード(例:"GO")との競合を回避する短い二文字の変数(QK、AK、OK、PK、FK)を使用し再定義可能なコントロールを実装しており、これにより

GET
を通じた動的キーマッピングが可能となり、文字セットの沈黙した上書きを防ぐ。将来の更新では、ゴブリンのカウンターアタック、複数の敵タイプ、霧の戦い、およびレベルシステムが約束されており、これは単一レベルのプロトタイプから、4K BASIC 環境内での現代的なエミュレーターサポートとともに、公平な勝ち負け条件を持つ完全なアドベンチャーへとプロジェクトを拡張する。

本文

追跡するゴブリンとメモリバグ:RGC シリーズ第 8 部

はじめに

前回の第 7 部ではダンジョン全体にゴブリンが湧いていましたが、彼らは配置された場所から一歩も動きませんでした。プレイヤーが攻撃しても去っていくだけでした。 今回からは、彼らがプレイヤーを追いかけてくるようになりました。 コードの小さな変更ですが、ゲームの「感触」における大きな前進です。

その過程で、キャラクターセットを破損させる奇妙なメモリバグに巻き込まれてしまいました。このバグこそがこのシリーズからの最大の教訓であり、軽くスルーせず、必ず目を通してください。

オンラインエディタへのアクセス ブラウザ上でソースコードを直接編集・実行できます(RGC オンライン IDE:

part8d.bas
)。ダウンロードや設定は一切不要です。


1. 前回までのあらすじ

第 7 部の着地点。

  • 独自のカスタム文字セットを読み込み。
  • ランダム生成された 3x3 メタタイルを基盤とするマップを表示。
  • D&D 風ステータスを備えたプレイヤーと、PEEK コリジョン検出システムを実装。
  • プレイヤーが隅に追い込まれた際に機能するテレポートキーを搭載。

しかし欠けていたのは「緊張感」。

  • 誰か脅かすものもなければ、勝敗やリスクも存在しませんでした。

この部分で変化する 4 つの要素

  • キー操作のカスタマイズ:
    QAOP
    という設定は万人の味ではありません。
  • ゴブリンのゲームオブジェクト化: 位置情報(X/Y)、健康値(HP)、および簡易 AI を装備。
  • 本格 d20 ロールによる戦闘: 筋力修飾子を考慮した攻撃判定を実装。
  • 自己書き換え問題の解決: 後述するほど複雑なメモリ問題を解消。

2. キー操作のカスタマイズ

QAOP
は幼少期から育った人々にとっては標準ですが、それ以外の層には非標準的です。両方の立場が正しいため、「どちらかを選ぶ」のではなく、「ゲーム側が文字通りのキー(リテラル)を参照するのをやめる」のが解決策です。

デフォルト値の格納

REM デフォルトのキー設定
QKEY$="Q"
AKEY$="A"
OKEY$="O"
PKEY$="P"
FKEY$="SPACE"

重要なのは最初の 2 文字だけです。 コモドール BASIC は変数名を厳密に 2 バイトしか保存しません(例:

PLAYERHEALTH
の内部では
PL
しか確認しない)。これにより、非常に不思議でデバッグが困難な挙動を引き起こしてしまいます。

同様に、キーワードが含まれるとトークン化エラーになります。

REM GL は GOLD にできない - GO が GOTO と衝突する (2 文字の変数名)
GL=0

SCORE
(OR を含む)、
COUNT
(ON を含む)など、変数名の中に BASIC のキーワードが含まれると構文エラーが発生します。

キー入力ルーチンの変更

入力チェックを「文字比較」から「変数比較」へ変更します。

IF P$=OKEY$ THEN PY=PY-1
IF P$=PKEY$ THEN PX=PX+1
IF P$=QKEY$ THEN PY=PY-1
IF P$=AKEY$ THEN PY=PY+1
IF P$=FKEY$ THEN GOSUB FIRE

入力ルーティン:GET の利用

キーリマップ画面では

INPUT
ではなく
GET
を使用します。

  • INPUT: ユーザーが入力して RETURN を押すまで待機(パニックを引き起こしやすい)。
  • GET: キーストロークバッファから単一の文字を即時に読み取り。

キー待ちのループ処理:

CHANGETHISKEY:
  GET K$: IF K$="" THEN GOTO CHANGETHISKEY
RETURN

これは「キーの有無チェック」です。選択したキーを押した後で RETURN を押してもらうのは誤った結果を招きます。

キー設定画面の実装

CHANGEKEYS:
  PRINT "{CLR}{GREY}"
  PRINT "キー変更"
  PRINT "==========="
  
  ' 上方向
  PRINT "デフォルト: QAOP スペース"
  PRINT "上方向のキーを押してください"
  GOSUB CHANGETHISKEY : QKEY$=K$
  
  ' 下方向
  PRINT "下方向のキーを押してください"
  GOSUB CHANGETHISKEY : AKEY$=K$

  ' 左方向
  Print "左方向のキーを押してください"
  GOSUB CHANGETHISKEY : OKEY$=K$

  ' 右方向
  Print "右方向のキーを押してください"
  GOSUB CHANGETHISKEY : PKEY$=K$

  ' 攻撃 (FIRE)
  Print "攻撃 (FIRE) のキーを押してください"
  GOSUB CHANGETHISKEY : FKEY$=K$

  ' 確認画面
  Print "設定で満足しましたか?(Y/N)"
HOLDFORKEY:
  GET A$
  IF A$="" THEN GOTO HOLDFORKEY
  IF A$="Y" THEN RETURN
  IF A$="N" THEN GOTO CHANGEKEYS
RETURN

注意点: ラベル名(

CHANGEKEYS
など)はオンライン IDE の利点です。物理マシンでは行数に変換されるため、読みづらくなります。


3. 追跡するゴブリンの実装

これまでのゴブリンはプログラム上には実体を持たず、単なる装飾品でした。移動させるためには、個体の管理(位置・HP)が必要です。

アレイによる管理

REM 敵変数の宣言
GC=0: REM GOBBO カウント(ゴブリン数)
DIM GH(10) : REM GOBBO HP アレイ
FOR GC=1 TO 10: GH(GC)=10: NEXT GC
GC=0
DIM GX(10) : DIM GY(10) : REM GOBBO リスト
  • GX / GY: ゴブリンの X/Y 座標を保持。
  • GH: HP を保持。
  • GC: 実際に配置した数をカウント。

メタタイルからの追加:

ADDGOBBO:
REM ゴブリンリストに追加 - GX=X, GY=Y (PX/PY と一致)
REM ガード:10 で止めて GC が DIM GX(10) を超えないようにする
IF GC>=10 THEN RETURN
GC=GC+1

' 中央座標へ修正(左上ではなく 3x3 ブロックの中央)
GX(GC)=COL+1
GY(GC)=ROW+1
RETURN

COL+1
ROW+1
は、ゴブリンが描画されている中央位置を指します。

敵 AI と移動ロジック

ゲームはターン制です(プレイヤー動作 → 敵動作 → チェック)。 単純にプレイヤー方向へ移動するロジック:

ENEMYLOGIC:
  IF GC=0 THEN RETURN
FOR G=1 TO GC
REM デッドなゴブリンをスキップ
IF GH(G)<=0 THEN GOTO NEXTENEMY

' プレイヤー方向へずらす
IX=GX(G) : IY=GY(G)

' X 座標調整
IF GX(G)>PX THEN IX=GX(G)-1   ' プレイヤーより右 -> 左へ移動
IF GX(G)<PX THEN IX=GX(G)+1   ' プレイヤーより左 -> 右へ移動
' Y 座標調整(プレイヤーより下 -> 上へ)
IF GY(G)>PY THEN IY=GY(G)-1   
IF GY(G)<PY THEN IY=GY(G)+1  

NEXTENEMY:
NEXT G
RETURN

重要: 移動先(

IX
,
IY
)と現在地(
GX
,
GY
)を分離して保持し、移動許可後に位置を更新します。

コリジョンチェック: ターゲットセルに画面コード 46(床の点)が含まれていれば空で、ゴブリンは移動可能です。壁やプレイヤーがいないかを確認します。

MOVEENEMY:
REM コース位置を古いゴブリンセルに設定して消去
GOSUB ERASEENEMY
REM 新しいセルに移動して描画
GX(G)=IX : GY(G)=IY
GOSUB DRAWENEMY
RETURN

FOR ループ内のラベル: COMODORE BASIC の

CONTINUE
コマンドが存在しないため、
NEXT
の直前にラベル (
NEXTENEMY:
) を置き、ループをスキップします(
GOTO
を使用)。


4. 戦闘ロールの実装

ゴブリンが移動後にプレイヤーに隣接した場合や、意図的に衝突させた場合に戦闘が始まります。

距離判定 (
ABS
の使用)

IF ABS(GX(G)-PX)<=1 AND ABS(GY(G)-PY)<=1 THEN GOSUB COMBAT

ABS
は符号を剥ぐため、両軸とも 1 マス以内であれば(斜め含む 9 マス内)、戦闘を開始します。

コマンド処理

COMBAT:
REM d20 ロール
R=RND(-TI)
D20=INT(RND(1)*20)+1

REM 筋力の修飾子を追加
MOD=INT((STATS(0)-10)/2)
D20=D20+MOD

REM ゴブリンの AC(8)に命中したか判定しダメージを決定
IF D20<=8 THEN MSG$="MISS!":GOSUB ALERT: HP=HP-5:GOSUB SHOWHUD:RETURN

' 攻撃成功時のダメージ計算
DMG=INT(RND(1)*8)+1+MOD
MSG$="ゴブリンに "+STR$(DMG)+" のダメージを与えた!":GOSUB ALERT

' HP 減算と死亡処理
GH(GC)=GH(GC)-DMG
IF GH(G)<=0 AND G>0 THEN MSG$="ゴブリン死んだ!":GOSUB ERASEENEMY:GOSUB ALERT
RETURN
  • d20 ロール:
    INT(RND(1)*20)+1
    で 1〜20 の乱数を生成。
  • 能力値:
    STATS(0)
    は筋力で、+3 などと計算される修正値を取得。
  • 命中判定: ゴブリンの AC(8)より小さいとミスし、ダメージを受けると同時に攻撃者が
    -5
    ダメージ。

5. カスタム文字セットを食い尽くしたバグ

ゴブリンのアレイを追加すると、画面が乱码になり、カスタム文字セットが破損しました。これはいわゆる メモリ割り当ての衝突 です。

問題の背景

  • VIC-II は一度に 16K(アドレス 0〜16383)のみを表示可能。
  • デフォルトでは下部 16K を使用しているが、文字セットをここに置くと BASIC プログラムと衝突する。
  • 第 7 部の問題点: 4K の文字セット全体を読み込み、大文字セットの半分(未使用領域)まで BASIC に侵入していた。

アドレスマッピング比較表

アドレス範囲第 7 部 (4K セット)第 8 部 (2K セット)状態
2049〜BASIC プログラム、変数、アレイ同じくプログラムが上へ成長
12288文字セット開始 (衝突)文字セット開始旧セットは成長をブロック
~14336BASIC 用の空き領域 (浪費)文字セット (未使用小文字セーフ)第 7 部ではスペースが浪費
14336-文字セット開始、BASIC はここで止まる新しい 2K セットは安全な場所
16383VIC-II の終了VIC-II の終了最大可視メモリ

解決策:文字セットのトリミングと移動

  • 必要な大文字セットのみ(2K)を読み込み、アドレスを
    14336
    に設定。
  • ファイル名:
    CHARS.BIN
    CHARS8C.BIN
    (ファイルサイズは半減)。

VIC-II のレジスタ変更

画面メモリと文字メモリの境界を変更します。

POKE 53272,(PEEK(53272)AND240)+14
  • PEEK(53272)
    :現在の値を読み取る。
  • AND 240
    :下位 4 ビットをマスク(画面メモリ部分を残す)。
  • +14
    :文字セットの新しいオフセット(14 / 2 = 7 → 14336)を設定。

BASIC のメモリ制限の設定

BASIC に「ここで停止する」と指示し、新たな領域で動作させるようにします。

REM メモリ制限対策:
IF PEEK(2)<>73 THEN POKE 55,0:POKE 56,56:POKE 2,73:CLR
  • POKE 55,0 : POKE 56,56
    : メモリポインタを 14336 に設定。
  • POKE 2,73
    : 修正フラグを設定(73 は恣意的な値)。
  • CLR
    : 必須。BASIC は内部の帳簿を再計算させる必要があるため、ポインタ変更後に実行。

再起動時の処理ロジック

IF PEEK(2)<>73 THEN POKE 55,0:POKE 56,56:POKE 2,73:CLR

REM カウンタで初期化状態を管理
IF A=0 THEN PRINT CHR$(147)"読み込み中、お待ちください"
A=A+1
IF A = 1 THEN GOTO CHARS       ' 文字セットを読み込む
IF A = 2 THEN GOTO SETCHARS     ' ポインタと制限を設定

CHARS:
LOAD "CHARS8C.BIN",8,1
SETCHARS:
POKE 53272,(PEEK(53272)AND240)+14
  • フラグ管理の注意点:
    CLR
    は全てをリセットするため、変数
    A
    もゼロに戻されます。しかし、修正フラグであるアドレス 2 の値(
    PEEK(2)=73
    )は
    CLR
    に影響されません。そのため、電源オフを除き、一度設定すれば再起動時も維持されます。
  • 冷起動時のリスク: アドレス 2 に偶然 73 が含まれる確率は低く、修正が実行されない場合、文字セットを食い尽くす可能性があります。

教訓: 8 ビットマシンではメモリは共有資源であり、BASIC、VIC-II、KERNEL、そしてコードがすべて同じ 64K で動作します。誰かが足を撃つのを止めません。


6. 次に何をするか

現状の

FIRE:
サブルーチンには頭方向の処理しか含まれていません。今後のアップデート計画:

  • ダメージを与えるゴブリン: 単純な接触ではなく、攻撃行為自体を実装。
  • 公平な敵生成: ランダムマップでのゴブリン配置バランス調整。
  • 勝敗条件: 健康値が負になった際の処理(ゲームオーバー)の実装。
  • 複数の種類の敵: 「プレイヤーへ向かう」以外の移動パターン追加。
  • 霧の戦争 (Fog of War): ダンジョン全体を一度に表示せず、視界制限の実装。
  • 階段と階層: 新たなエリアへの移動ロジックを追加。

プログラム全体は IDE で確認・改変可能です(

part8d.bas
)。ゴブリンの AC を変更したり、知能レベルを上げたりして試してみてください。

同じ日のほかのニュース

一覧に戻る →

2026/07/19 23:41

Show HN:12万ドルのボウリングセンターシステムを、ESP32 1,600 ドルで置き換えました

## 日本語訳: このプロジェクトは、8レーンの郊外ボウリングセンターにおける重要なインフラストラクチャ問題を解決することを目的としています。同センターでは、2008 年の過時化した機械式スコアリングシステムが置換される必要があり、そのコストは 105,000 米ドルから 120,000 米ドルに上っています。著者(施設を運用する SRE)はこの高額な障壁とベンダーロックインを回避するために、コモディティ技術に基づいたカスタム・オープンソースのスタックを提案しています。このソリューションでは、RS485 ワイアードフォールバックを備えた ESPNow メッシュトポロジーで接続された ESP32 マイコンをノードに使用し、Raspberry Pi レーンコンピュータを Redis イベントストリーミングゲートウェイとして採用しています。このアーキテクチャにより、堅牢なデータ所有権の実現、トロンテーマのアニメーションのようなカスタマイズ可能な機能、ボールスピード計算やピン検出など的高度なロジックが可能になります。主な課題は各ノードに対して専用のファームウェアを開発することでしたが、結果的に作成されたプロトタイプのコストは約 1,600 米ドルに留まり(交換部品費数千米ドルに対して)、レーンペアあたり約 200 米ドルです。また、システムへの迅速な修理(5 分以内)やシステムのスワップ(10 分以内)も可能です。ハードウェア、ファームウェア、ソフトウェアを含む全設計は、OpenLaneLink でリリースされる予定であり、プロプライエタリ制約のない近代的なスコアリング機能を取り入れたい施設にとって、参入障壁を大幅に低下させるものです。

2026/07/14 23:23

並列プログラミングの禅

## Japanese Translation: 真の進歩は、単に計算資源や人的リソースを増加させることによって達成されるのではなく、すべての構成要素間の効果的な調整を必要とします。プロセッサや人材を増やすだけでは、元素同士の間で資源を競合させたり、孤立して動作したりするとシステムのスロットル化や燃え尽きをもたらすため、失敗することが往々にしてあります。この原理は『禅の心・初心者の心』に見られる教えに準拠しており、全身全霊の活動は残り物なく完全に燃える清潔な火に例えられています。同様に、ソフトウェアシステムにおいて隠された情報が不安を引き起こすように、不整合な人間の知性と感情は疲れをもたらします。 今後、気候モデル化や創薬のような複雑な全球的課題を解決するには、単に新たな能力を獲得するだけでなく、既存の能力との同期を mastery する必要があります。人工知能や大規模データ解析に依存する産業は、生ハードウェアの拡張から内部通信の最適化とワークフロー統合へと焦点を移さなければなりません。また、個人やチームも感情的な深さと知的創造性を整合させる包括的なアプローチを採用する必要があります。これらの重要な同期問題を解決しない場合、人類は権力の分断がさらなる進化和理解を停止させるという厳しい天井に直面するリスクにあります。

2026/07/20 3:57

ホームラボ #1:MikroTik を家庭用ルーターとして採用する

## Japanese Translation: 本ガイドでは、自宅ラベル用にISPの設備を置き換えるマイクロティク L009UiGS-RMルーターの設定を詳述し、ローカルバックアップの活用およびネットワークパフォーマンスの最適化を実現します。プロセスは、IPoE または PPPoE のいずれかであるなど接続の特定から始まり、MAC クローンリングによるハードウェアバインディングへの対応へと続きます。重要な決定要因となるのが IPv4 アドレスの割り当てであり、ISP からプライベート IPv4 アドレス(キャリアグレード NAT)が提供される場合、パブリック IP アドオンを購入しない限り入方向的接続はブロックされ、DS-Lite 構成では MikroTik の自動 AFTR サポートがないためポートフォワーディングが破綻する可能性があります。この特定のセットアップでは、著者は VLAN 35 を介した PPPoE およびプライベート IPv4 アドレスを使用しています。 設定には、WAN リンク(ether1)上で VLAN インターフェースを作成し、ISP に接続するための PPPoE クライアントを確立することが含まれます。大量転送時のバッファーブloat によるレイテンシを緩和するため、ガイドでは `fq-codel` キューイングアルゴリズムを採用しており、このキューを経由するようにトラフィックが通過するようファストトラックファイアウォールルールの無効化が必要です。無線管理は、ポート 8 に接続された別個の PoE 給電アクセスポイント上で CAPsMAN を使用して行われます。結局のところ、このプロセスはユーザーに完全なネットワーク制御を付与し、可能な限り制約のある ISP の制限(例えば CGNAT)を回避するとともに、感応度が高いアプリケーションに対して信頼性が高く最適化された接続を提供します。

C64 バージョンのバシック言語ダンジョンクローラー:ゴブリン襲撃(C64 バージョンの一部8) | そっか~ニュース