Rogue 3.6.3: プレイヤーのデータ構造

改めてRogueのコードを読み始めたのでメモ。読んでいるのはRoguelike Restoration ProjectでダウンロードしたRogue 3.6.3(r1043)。
プログラムが実行されると、画面サイズのチェックやら、OS依存のコードやらの後、まずinic.c内のinit_playerが呼び出される。プレーヤーとモンスターはどちらも同じ構造体でデータが保持され、その名前はthingである。rogue.hにて定義されている。

struct thing {
    coord t_pos;			/* Position */
    bool t_turn;			/* If slowed, is it a turn to move */
    char t_type;			/* What it is */
    char t_disguise;			/* What mimic looks like */
    char t_oldch;			/* Character that was where it was */
    coord *t_dest;			/* Where it is running to */
    short t_flags;			/* State word */
    struct stats t_stats;		/* Physical description */
    struct linked_list *t_pack;		/* What the thing is carrying */
    int t_reserved;         /* reserved for save/restore code */
};

モンスターにも使われるため、「ミミックが何に化けているか(t_disguise)」とか「どこに向かって走っているか(t_dest)」とかがあって楽しい。またプレーヤーの場合、その構造の一部は別名が用意されているのでややこしい。

#define hero player.t_pos
#define pstats player.t_stats
#define pack player.t_pack

ステータスが保存されているstats構造体(プレーヤーのstatsはpstatsでアクセス可能)は以下の通り。

struct stats {
    str_t s_str;			/* Strength */
    long s_exp;				/* Experience */
    int s_lvl;				/* Level of mastery */
    int s_arm;				/* Armor class */
    int s_hpt;				/* Hit points */
    char s_dmg[30];			/* String describing damage done */
};

わかりやすい。ちなみにs_dmgは与えられるダメージの大きさを保存する文字列で「3d6」みたいな文字列を直接保存する。ちなみにこれは6面体サイコロ3つ分って意味。「1d4」なら4面体サイコロ1つ、つまり1〜4のダメージを与えることができる。
保持している品物は、linked_listという構造体に保持されている(プレーヤーの所持リストはpackでアクセス可能)。これは単なる双方向リスト。l_dataにお好きなポインタを入れてね、ということらしい。

struct linked_list {
    struct linked_list *l_next;
    struct linked_list *l_prev;
    char *l_data;			/* Various structure pointers */
};

coodは、位置を表す構造体。

typedef struct {
    int x;
    int y;
} coord;

そしてinit.cのプレーヤーの初期化部分。

init_player()
{
    pstats.s_lvl = 1;
    pstats.s_exp = 0L;
    max_hp = pstats.s_hpt = 12;
    if (rnd(100) == 7)
    {
	pstats.s_str.st_str = 18;
	pstats.s_str.st_add = rnd(100) + 1;
    }
    else
    {
	pstats.s_str.st_str = 16;
	pstats.s_str.st_add = 0;
    }
    strcpy(pstats.s_dmg,"1d4");
    pstats.s_arm = 10;
    max_stats = pstats;
    pack = NULL;
}

これを見ると、100分の1の確率でSTRENGTHが大幅にあがって強くなることがわかる。それ以外は固定値。最初のダメージは1d4で1〜4。持ち物は最初は何もなくてNULLになっている。ここではまだ位置情報などは設定されない。