憂鬱な勇者.c

http://d.hatena.ne.jp/hrkt0115311/20080527/1211891558
今ごろ…。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#ifdef _WIN32
#include <windows.h>
#define sleep(s) Sleep((s) * 1000)
#define snprintf(s, n, f, ...) sprintf_s((s), (n), (f), __VA_ARGS__)
#else
#include <unistd.h>
#endif

#define BUFSIZE        256
#define SUPREMUM       10000
#define SUPREMUM_DIGIT 4
#define MAXLEVEL       30
#define MONSTER_NUM    30
#define SKILL_NUM      30

#define ENCOUNTER "\
*-----\n\
%sを倒した!\n\
%sの経験値を得た。\n\
勇者は%dにレベルが上がった!\n\
勇者は、%sを覚えた。\n\
\n\
"

#define BLA_BLA_BLA "\
\n\
そして、\n\
かくかくしかじかで、山あり谷ありの冒険が続いたが割愛。\n\
\n\
"

#define EPILOGUE "\
*-----\n\
%sを倒した!\n\
%sの経験値を得た。\n\
勇者は、また、レベルが上がった!\n\
勇者は、ふと空しさを覚えた。\n\
\n\
"

static const char *monsters[MONSTER_NUM] = {
  "焼きたてパン",
  "強いシャチホコ",
  "もんじゃ焼き一年生",
  "怪人ホタテ男",
  "ニセ勇者",
  "逃げ足の早いアレ",
  "睡魔",
  "煩悩",
  "愛らしい子犬の中の人",
  "恋するスズメバチ",
  "勇敢なクマンバチ",
  "信じられない物",
  "勇者の師匠",
  "浮遊する鎧",
  "怪盗ドボン",
  "闇の招き猫",
  "誘惑のカスタードクリーム",
  "しょっぱすぎる籠手",
  "カレー味の兜",
  "光沢だけは一流の盾",
  "若葉マークのモンスター",
  "新緑の季節",
  "梅雨時の車両のニオイ",
  "暑すぎる夏",
  "新宿らしき何か",
  "やたら発達したドーナツ",
  "育ちすぎたクマー",
  "なごやかな雰囲気",
  "凍り付いた気配",
  "忍び寄る恐怖",
};

static const char *skills[SKILL_NUM] = {
  "お豆腐の買い方",
  "鉛筆の買い方",
  "消しゴムの使い方",
  "メモの取り方",
  "攻撃に使えないこともない呪文",
  "裏町の歩き方",
  "森林浴",
  "珈琲の味",
  "しじみのみそ汁の作り方",
  "回覧板の回し方",
  "郵便物の投函方法",
  "立ち話のコツ",
  "猫の呼び方",
  "犬の呼び方",
  "カラスの呼び方",
  "鳩専用豆鉄砲",
  "秘密の趣味",
  "速く走るコツ",
  "剣の使い方",
  "斧の使い方",
  "まきわりで、まっきわりわり",
  "聖なる祈り",
  "孤独",
  "涼しく過ごすコツ",
  "お洒落のコツ",
  "卵をふわっと焼く方法",
  "ごはんの研ぎ方",
  "油汚れの対応方法",
  "大人の振るまい",
  "Suicaの使い方",
};

static void multi_bignum(int *bignum, int *len, int n) {
  int carry = 0, i;

  for (i = 0; i < *len; i++) {
    long tmp = bignum[i];
    tmp = tmp * n + carry;
    bignum[i] = tmp % SUPREMUM;
    carry = tmp / SUPREMUM;
  }

  if (carry > 0) {
    bignum[i] = carry;
    (*len)++;
  }
}

static void fact(int *bignum, int *len, int n) {
  int i;
  bignum[0] = 1;

  for (i = 1; i <= n; i++) {
    multi_bignum(bignum, len, i);
  }
}

char *fact2str(int n) {
  int bignum[BUFSIZE], len = 1, i;
  char *dest, *p, *fmt = "%d";

  fact(bignum, &len, n);
  dest = malloc(len * SUPREMUM_DIGIT + 1);
  p = dest;

  for (i = len - 1; i >= 0; i--) {
    snprintf(p, SUPREMUM_DIGIT + 1, fmt, bignum[i]);
    while(*p) { p++; }
    fmt = "%04d";
  }

  return dest;
}

int main() {
  int level;

  srand((unsigned int) time(NULL));

  for (level = 1; level <= MAXLEVEL; level++) {
    const char *monster = monsters[rand() % MONSTER_NUM];
    const char *skill = skills[rand() % SKILL_NUM];
    char *exp = fact2str(level);

    if (level < MAXLEVEL) {
      printf(ENCOUNTER, monster, exp, level, skill);
      sleep(2);
      printf(BLA_BLA_BLA);
      sleep(2);
    } else {
      printf(EPILOGUE, monster, exp);
    }

    free(exp);
  }

  return 0;
}