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になっている。ここではまだ位置情報などは設定されない。