内容に「C」を含む
91〜100件目 / 224件
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 次へ

 ナミヤ雑貨店の奇蹟 / magicien 

ナミヤ雑貨店の奇蹟 2013年の一冊目。東野圭吾さんのナミヤ雑貨店の奇蹟を読んだ。


言わずと知れた理系作家の作品ということで、さぞ複雑なトリックを使う知能犯が登場するのだろうと思いきや、頼り無さそうな3人組の強盗犯が逃げる場面から物語が始まります。
その逃亡犯が一晩の潜伏先に選んだのが、廃屋となっていたナミヤ雑貨店。そこで3人は不思議な出来事に遭遇して...という話。

例によってネタばれしそうなので内容は書けませんが、いくつかの時間軸と何人かの登場人物が出て来て、時間軸×登場人物の数だけシーンが合って、それが割とバラバラに出て来るので、一気に読まないと分からなくなりそうです。
ミステリーではなくファンタジーに近いですが、終盤で次々と伏線が回収されていくのは、さすがミステリー作家という感じです。

話の内容は全く違いますが、「時間軸×登場人物」という形式の物語として、99人の最終電車というハイパーテキスト小説なるものを以前(一部を)読みました。
1996年というウェブの黎明期とも呼べるような時代から連載が開始されていて、初めて読んだときは、こんな小説があるのかと衝撃を受けた記憶があります。既に完結していますが、今でもウェブ上で公開されているので、読んだことが無い人は、一人分の物語だけでも読んでみてもらえればと思います。
「99人の最終電車」のような形式の作品に興味を持つきっかけになったのは別の作品(ゲーム?)なのですが...まだ公開されているのかどうか。もし見つけたら紹介したいと思います。
WebGLとかARとかがもっと広まれば、体験型推理小説みたいなものも出てくるような気がしますが...小説というよりゲームに分類されてしまうんだろうか。

2013/01/03(Thu) 20:29:48

 あけましておめでとうございます / magicien 

2013年もよろしくお願いします。


今年の目標はこんな感じで行こうと思います。
  • MMD杯参加
  • 簿記1級取得
  • 特殊小型船舶免許取得
  • TOEIC 860点取得
  • WebGLライブラリのドキュメント作成
  • I.Q REVENGE完成版作成
  • WebGLのゲームを作成
  • 何かしらの海外のコミュニティに参加
  • GIMP(かSeashore)に慣れる
  • 読書50冊

無理矢理ひねり出して10個にしました。
いつぞやの年に立てた目標よりスケールが小さくなっている気がしますが、いつも大それた目標を立てて失敗しているので、今回は頑張れば実現できそうなものにしてみました。
趣味と語学とWebGLといった感じです。今年からは趣味に読書を挙げられるよう頑張って本を読もうと思います。

ちなみに、今年の初夢は、広大で複雑な学校(たぶん高校。小学校が隣接していて敷地がつながっているので余計に複雑)で授業に間に合うべく教室へ向かって頑張って走るも、迷った挙げ句遅刻が確定する、というもの。
現実になってたまるか、という内容ですが、ゲームにしたらシュールな感じで面白いかなと思いました。
時間割に合わせて、いろんな教室を回りつつ定期的にトイレによったり昼食食べたり、とか。シュール...

2013/01/03(Thu) 03:28:09

 魔王 / magicien 

魔王 (講談社文庫) 伊坂幸太郎さんの「魔王」。最近本の話ばかりですが、せっかく読んだので。

読んだタイミングが良かったのか、悪かったのか、超能力と政治と選挙の話。
「魔王」「呼吸」の二部構成になっていて、それぞれ2004年12月、2005年7月に書かれたもの。なのですが、巻末の解説にも書いてある通り、未来の出来事を予言するかのような内容でした。

続編にあたる「モダンタイムス」という作品も出ているようなので、今度読んでみようかと思います。
タイトルの「魔王」は、シューベルトの曲から。作中の登場人物は曲の印象を「恐ろしい」と語っていたけれど、私が小学校だか中学校だかの音楽の授業で聞いたときは、みんなで爆笑した記憶が...日本語版を聞いたのがいけなかったのかもしれない。そのとき音楽の先生がどんな顔をしていたのかはよく覚えていない。まぁ、「パンをふんだ娘」を見て笑い転げていたような子だったので、感性が多少アレだったのかも。歌で恐怖を表現するっていうのは難しいものです。
それにしても、伊坂さんの作品は当たり前のように登場人物たちが死んでいくので、読むときは身構えてしまいます。

そういえば、Amazonでこの本を検索したときに、ISBNコードが無い「魔王」が検索にヒットして、バグかと思ったらKindle版でした。電子書籍ってISBNコードはどうなるんだろう。

2012/12/10(Mon) 01:21:35

 冷たい校舎の時は止まる / magicien 

冷たい校舎の時は止まる(上) (講談社文庫) 辻村深月さんのデビュー作。上下巻を一気に読んだ。

11月の記事が抜けてしまうなぁと思い、10月に読んだ本の感想でも書いてみる。
本屋で辻村さんの本が大量に平積みされていたので、とりあえずデビュー作から読んでみようということで、買ってみました。
買ってから気づいたけど、上下巻合わせると結構分厚い。
ノリオがときどき京極夏彦さんの本の感想を書いているので、どれどれと思って京極さんのコーナーに行くと、その本棚だけ異様な雰囲気を醸し出していますが、辻村さんの本も本棚に横に並べれば同じような空気になりそう。

内容は、ある朝登校した8人の高校生が時間の止まった校舎に閉じ込められて...という話で、ミステリーというよりホラーに近いかもしれません。
8人がそれぞれ抱えている悩みが話のメインになっていて、しかもその悩みが割とリアルだったりして、読んでいて古傷が痛んだりするわけで、死人が蘇るより、過去のトラウマが蘇る方がよほど恐ろしかったりするわけです。

ところで、この本では辻村深月という人物が出てくるけど、作者とこの人物は同じような性格ということなんだろうか。
2012/11/30(Fri) 23:00:00

 すべてがFになる / magicien 

すベてがFになる (講談社文庫) 森博嗣さんの作家としてのデビュー作であり、私が夏休みに読むはずだった1冊。本文を書きすぎてセッションが切れて、内容全部ふっとんだけど泣きながらもう一回書く。

冒頭で登場人物の紹介があり、プログラマが何人かいたので、おぉっ?と思って興味が湧いたと同時に、タイトルの意味について何となく察しがついた。
それにしても、作品の最初にオブジェクト指向の本を引用するのも驚いたし、「それでは、なぜ人間は交換をするのであろう」という文から始まり人間の脳の構造から説明をしているオブジェクト指向の本があるのにも驚いた。

私の勝手なイメージでは、森さんは機械工学には精通しているけど、ソフトウェア工学はあんまり、という感じだと思っていましたが、よくよく調べるとBASICやCの本も書いていたんですね。
小説を書く場合、テーマを決めてから、そのテーマについて詳しく調べていき、話の中身を考えるという作り方が一般的なのではないかと思う(ビブリア古書堂の古書なんかはそうだと思う)のだけど、森さんの場合は、既に持っている知識の中からテーマを選び、そこにミステリーの肉付けをしているような気がする。というより、書きたいことを書いて本にするためにミステリィの体裁をとっている、という印象。

それはさておき、本の感想に戻ると、プログラムやOSに関する話が随所に出て来て、わくわくしながら読めました。使っているエディタがemacsなのかviなのかは気になるところ。1995年に書かれた本ということで、内容は少し古いですが、それはそれで楽しめると思います。あるいは、書かれた年代が謎解きのヒントになるかもしれません。
それと、途中で部屋の中の工具を列挙していく場面があり、その気合いの入りっぷり、活き活きした感じはやはりというかさすがというか、先生、素が出てますよ!という感じで見所です。愛犬のトーマくんもちょろっと出演している模様。
このシリーズを読んだのはこれが初めてですが、作品の一番最後に登場した人物がシリーズ後半でのモリアーティ教授的存在になるのかなぁと思ったり。

2012/10/08(Mon) 17:09:03

 JavaScriptでテキストデータの読み込み / magicien 

JavaScriptでXファイルを読み込んだときに使った方法。

バイナリデータの読み込みについて書きかけの状態ですが、今回はテキストデータの読み込みについて。
実行速度よりも実装のしやすさを優先するなら、Ginがおすすめ。
実際の使い方としてはこんな感じ。
var xfileGrammar;
function start()
{
  xfileGrammar = new Gin.Grammar({
  XFile:         / XFileHeader:header (XObjectLong)* /,
  XFileHeader:   / 'xof ':xof VersionNumber FormatType:showValue FloatSize:showValue /,
  VersionNumber: / <\d\d>:showValue <\d\d>:showValue /,
  FormatType:    / 'txt ' | 'bin ' | 'tzip' | 'bzip' /,
  FloatSize:     / '0064' | '0032' /,
 
  XObject:       / Template | Animation | AnimationKey | AnimationOptions | AnimationSet | AnimTicksPerSecond | Boolean | Boolean2d | ColorRGB | ColorRGBA | Coords2d | DeclData | EffectDWorld | EffectFloats | EffectInstance | EffectParamDWorld | EffectParamFloats | EffectString | FaceAdjacency | FloatKeys | Frame | FrameTransformMatrix | FVFData | Header | IndexedColor | Material | Matrix4x4 | MeshFaceWraps | MeshFace | MeshMaterialList | MeshNormals | MeshTextureCoords | MeshVertexColors | Mesh | Patch | PatchMesh9 | PatchMesh | PMAttributeRange | PMInfo | PMVSplitRecord | SkinWeights | TextureFilename | TimedFloatKeys | Vector | VertexDuplicationIndices | VertexElement | XSkinMeshHeader /,
  XObjectLong:   / Template | AnimationLong | AnimationKeyLong | AnimationOptionsLong | AnimationSetLong | AnimTicksPerSecondLong | BooleanLong | Boolean2dLong | ColorRGBLong | ColorRGBALong | Coords2dLong | DeclDataLong | EffectDWorldLong | EffectFloatsLong | EffectInstanceLong | EffectParamDWorldLong | EffectParamFloatsLong | EffectStringLong | FaceAdjacencyLong | FloatKeysLong | FrameLong | FrameTransformMatrixLong | FVFDataLong | HeaderLong | IndexedColorLong | MaterialLong | Matrix4x4Long | MeshFaceWrapsLong | MeshFaceLong | MeshMaterialListLong | MeshNormalsLong | MeshTextureCoordsLong | MeshVertexColorsLong | MeshLong | PatchLong | PatchMeshLong | PatchMesh9Long | PMAttributeRangeLong | PMInfoLong | PMVSplitRecordLong | SkinWeightsLong | TextureFilenameLong | TimedFloatKeysLong | VectorLong | VertexDuplicationIndicesLong | VertexElementLong | XSkinMeshHeaderLong /,
 
  XString:       / <[0-9A-Za-z]*> /,
  Identifier:    / XString /,
  Name:          / XString /,
  UUID:          / '<' (<[0-9A-Za-z]|->)* '>' /,
  Member:        / ('array' TemplateType Name '[' ($INT | XString) ']') | (TemplateType Name) /,
  TemplateType:  / XString /,
  XArray:        / '[' $INT ']' /,
 
  XObjectTemplate:       / Identifier:identifier Name:name '{' UUID ('[...]' | ('[' Name ']') | (Member ';'))* '}' /,
  Template:             / 'template':template  Name '{' UUID ('[...]' | ('[' Name ']') | (Member ';'))* '}' /,
 
  IntValue:             / $INT ';' ::first /,
  IntArray:             / $INT (',' $INT)* (',')? ';' /,
 
  FloatValue:           / $REAL ';' ::first /,
  FloatArray:           / $REAL (',' $REAL)* (',')? ';' /,
 
  Header:               / HeaderLong | (HeaderValue ';') /,
  HeaderLong:           / 'Header' (Name)? '{' (UUID)? HeaderValue '}' /,
  HeaderValue:          / IntValue:major IntValue:minor IntValue:flags /,
 
  Animation:            / AnimationLong | ( AnimationValue ';') /,
  AnimationLong:        / 'Animation' (Name)? '{' (UUID)? AnimationValue '}' /,
  AnimationValue:       / $ANY /,
 
  AnimationKey:         / AnimationKeyLong | ( AnimationKeyValue ';') /,
  AnimationKeyLong:     / 'AnimationKey' (Name)? '{' (UUID)? AnimationKeyValue '}' /,
  AnimationKeyValue:    / $ANY /,
 
  AnimationOptions:      / AnimationOptionsLong | ( AnimationOptionsValue ';') /,
  AnimationOptionsLong:  / 'AnimationOptions' (Name)? '{' (UUID)? AnimationOptionsValue '}' /,
  AnimationOptionsValue: / $ANY /,
 
  AnimationSet:         / AnimationSetLong | ( AnimationSetValue ';') /,
  AnimationSetLong:     / 'AnimationSet' (Name)? '{' (UUID)? AnimationSetValue '}' /,
  AnimationSetValue:    / $ANY /,
 
  AnimTicksPerSecond:      / AnimTicksPerSecondLong | ( AnimTicksPerSecondValue ';') /,
  AnimTicksPerSecondLong:  / 'AnimTicksPerSecond' (Name)? '{' (UUID)? AnimTicksPerSecondValue '}' /,
  AnimTicksPerSecondValue: / $ANY /,
 
  Boolean:              / BooleanLong | ( BooleanValue ';') /,
  BooleanLong:          / 'Boolean' (Name)? '{' (UUID)? BooleanValue '}' /,
  BooleanValue:         / $ANY /,
 
  Boolean2d:            / Boolean2dLong | ( Boolean2dValue ';') /,
  Boolean2dLong:        / 'Boolean2d' (Name)? '{' (UUID)? Boolean2dValue '}' /,
  Boolean2dValue:       / $ANY /,
 
  ColorRGB:             / ColorRGBLong | (ColorRGBValue ';') /,
  ColorRGBLong:         / 'ColorRGB' (Name)? '{' (UUID)? ColorRGBValue '}' /,
  ColorRGBValue:        / FloatValue:red FloatValue:green FloatValue:blue /,
 
  ColorRGBA:            / ColorRGBALong | (ColorRGBAValue ';') /,
  ColorRGBALong:        / 'ColorRGBA' (Name)? '{' (UUID)? ColorRGBAValue '}' /,
  ColorRGBAValue:       / FloatValue:red FloatValue:green FloatValue:blue FloatValue:alpha /,
 
  Coords2d:             / Coords2dLong | (Coords2dValue ';') /,
  Coords2dLong:         / 'Coords2d' (Name)? '{' (UUID)? Coords2dValue '}' /,
  Coords2dArray:        / Coords2dValue (',' Coords2dValue)* (',')? ';' /,
  Coords2dValue:        / FloatValue:u FloatValue:v /,
(中略)
  XSkinMeshHeader:      / XSkinMeshHeaderLong | ( XSkinMeshHeaderValue ';') /,
  XSkinMeshHeaderLong:  / 'XSkinMeshHeader' (Name)? '{' (UUID)? XSkinMeshHeaderValue '}' /,
  XSkinMeshHeaderValue: / $ANY /,
}, "XFile", Gin.SPACE);

function XFileHandler() { this._s = [] };
XFileHandler.prototype = {
  first: function(v){ return v[0]; },
  header: function(v){ alert("version: " + v[1]); },
  identifier: function(v){ alert("identifier:" + v[0]); },
  xof: function(v){ alert("xof"); },
  showValue: function(v){ alert("value:" + v); },
  name: function(v){ alert("name:" + v); },
(中略)
  // Mesh
  mesh:      function(v){ alert("Mesh start"); },
  nVertices: function(v){ alert("nVertices: " + v); },
  vertices:  function(v){},
  nFaces:    function(v){ alert("nFaces: " + v); },
  faces:     function(v){},
(中略)
};
 
var match;
function parseXFile(request)
{
  var text = request.responseText;
  var handler = new XFileHandler();
  match = xfileGrammar.parse(text, handler);
  if(match && match.full) {
    alert("OK");
  }else{
     alert("NG");
  }
}

var url = "xfile.x";
var myAjax = new Ajax.Request(
  url,
  {
    method: 'get',
    onComplete: parseXFile
  });
}
パースしたいデータの構文が分かっているなら、それをそのまま書いてやれば簡単にパーサが実装できる。
速度を優先するなら、各ファイル形式に合わせて自分で実装すべし。
xファイルのパーサはこんな感じで作りました。
var XParser = Class.create({
  _text: null,
(中略)
  parse: function(text){
    this._text = text;
    if(!this._obj){
      this._obj = new XModel();
    }
    this._offset = 0;
    this._err = 0;

    if(!this.XFileHeader(this._obj)){
      alert("header format error");
      this._err = 1;
      return null;
    }
    while(this.XObjectLong(this._obj)){}
    if(this._err){
      alert("obj format error:" + this._err);
      return null;
    }
    this.splitFaceNormals();

    return this._obj;
  },

  moveIndex: function(len) {
    this._text = this._text.substring(len);
    this._offset += len;
  },

  getString: function(pattern) {
    this.skip();
    var str = this._text.match(pattern);
    if(str != null){
      this.moveIndex(str[0].length);
      return str[0];
    }
    return null;
  },

  /* matching patterns */
  skip: function() {
    var i=0;
    var code;
    while(1){
      code = this._text.charCodeAt(i);
      if(code != 32 && (code < 9 || code > 13)){
        break;
      }
      i++;
    }
    if(i>0){
      this.moveIndex(i);
    }
  },

  _integerPattern: new RegExp(/^(-|\+)?\d+;?/),
  getInteger: function() {
    var str = this.getString(this._integerPattern);
    var val = parseInt(str);
    return val;
  },

  _floatPattern: new RegExp(/^(-|\+)?(\d)*\.(\d)*;?/),
  getFloat: function() {
    var str = this.getString(this._floatPattern);
    var val = parseFloat(str);
    return val;
  },
(中略)
  XObjectLong: function(parent){
    var id = this.getWord();
    if(id == null){
      return null;
    }
    switch(id){
      case "template":
        return this.Template(parent);
      case "Header":
        return this.Header(parent);
      case "Mesh":
        return this.Mesh(parent);
      case "MeshMaterialList":
        return this.MeshMaterialList(parent);
      case "MeshNormals":
        return this.MeshNormals(parent);
      case "MeshTextureCoords":
        return this.MeshTextureCoords(parent);
      case "MeshVertexColors":
        return this.MeshVertexColors(parent);

      default:
        alert("unknown type:" + id);
        break;
    }
    return false;
  },
(中略)
  Mesh: function(parent) {
    this.getLeftBrace();

    // vertices
    var nVertices = this.getInteger();
    var skinArray = $A();
    for(var i=0; i<nVertices; i++){
      var skin = new Skin();
      var pos = new DHVector3();
      pos.x = this.getFloat();
      pos.y = this.getFloat();
      pos.z = -this.getFloat();
      skin.position = pos;

      skin.boneIndex[0] = 0;
      skin.boneIndex[1] = -1;
      skin.boneIndex[2] = -1;
      skin.boneIndex[3] = -1;

      skin.skinWeight[0] = 1;
      skin.skinWeight[1] = 0;
      skin.skinWeight[2] = 0;
      skin.skinWeight[3] = 0;

      skinArray.push(skin);

      this.getCommaOrSemicolon();
    }
    this._obj.skinArray = skinArray;
    this._obj.dynamicSkinOffset = -1;

    // faces
    var nFaces = this.getInteger();
    var faces = $A();
    for(var i=0; i<nFaces; i++){
      var face = this.getIntegerArray();
      faces.push(face);
    }
    this._indices = faces;
    this.getRightBrace();

    return true;
  },
(中略)
}

2012/10/05(Fri) 01:21:39

 静的ファイルのキャッシュ無効化(JavaScriptの場合) / magicien 

ウェブサーバ上でプログラムからtxtファイルを頻繁に更新しているような場合、ウェブブラウザでキャッシュ機能が有効になっていると(というか大抵なっているので)、ローカルにあるキャッシュを見に行ってしまい、サーバ上の最新のtxtファイルを見に来てくれない、という場合の対応。

時と場合によりやり方はいろいろあるんだろうけど、JavaScriptでは次のようなソースを書いた。
var url = "dynamic_content.txt";
url += "?" + (new Date() * 1); // disable cache

var data;
new Ajax.Request(fileName, {
  method: 'get',
  asynchronous: false,
  onComplete: function(result){
    data = result.responseText;
  },
});
URLの後ろに時刻(ミリ秒)をクエリで追加してやると、あたかも違うファイルを呼び出しているように見えるので、毎回サーバまで読み込みに行くようになる。
上記の例だと、urlの中身は "dynamic_content.txt?1349282126489" のようになる。
new Date()のままだと、"Thu Oct 04 2012 01:35:26 GMT+0900 (JST)" のような文字列になるため、適当に数値計算をして、整数にキャストする。ただ、"new Date() + 0" みたいなことをすると文字列が連結され、"Thu Oct 04 2012 01:35:26 GMT+0900 (JST)0" となってしまうため、0を引くなり、1を掛けるなりしてやればOK。
まぁクエリが日付のままでも問題無いとは思いますが。
2012/10/04(Thu) 01:44:24

 Macのsayコマンド / magicien 

昨日紹介した動画中の「ファーストステージ」とか「パーフェクト」とかいう声は、Macのsayコマンドを使っています。

Macには元々スピーチ機能というのが付いていて、sayコマンドを使って簡単に喋らせることができます。
$ say 1st stage
こんなコマンドを実行すると、テキストを読み上げてくれます。
-vオプションで声の種類を選択することが可能で、I.Q REVENGEで使ったのは、Alexという声。
say -v Whisper でゴノレゴの声が!
読み上げの速度はコマンドのオプションからは指定できないのですが、システム環境設定の「スピーチ」から読み上げ速度の設定が可能で、設定した内容はsayコマンドの出力結果にも反映されます。

残念ながら日本語のテキストは読んでくれないので、ローマ字で頑張って書かなければいけません。また、英語の発音もそれなりだったり。"Perfect" のアクセントとか...
最初はミクさんにExcellent!としゃべらせようと悪戦苦闘していましたが、よくよく考えたらもっとそれっぽいのがMacに付いてるじゃん、ということでこちらにしました。
キューブに踏みつぶされたり、ゲームオーバのときは音量小さいですが、ミクさんの声を使ってます。
追記:Lionだと日本語も読んでくれるらしい。なん...だと...
2012/10/03(Wed) 01:35:57

 【MMD】ブラウザで踊ってもらった(その7)【WebGL】 / magicien 

先日、こっそりサンプルを公開したら、本当に誰も遊びに来てくれなかったので、紹介動画を作りました。


奇しくも、あれからちょうど半年。嘘が真になる裏エイプリルフールというやつです。
年内にその8を公開したいけど、ネタが無いなぁ。

2012/10/01(Mon) 23:52:15

 ビブリア古書堂の事件手帖―栞子さんと奇妙な客人たち / magicien 

ビブリア古書堂の事件手帖―栞子さんと奇妙な客人たち (メディアワークス文庫) 夏休み中、読もうと思って買った10冊の小説のうち、読み終わったのは2冊だけ... この本はそのうちの1冊。

売れに売れている本を紹介するのもあまり意味が無い気がしますが、自分の読書記録を兼ねて。
タイトルから分かるとおり、古書店を舞台にしたミステリー。
ミステリーといえば探偵役が必要なわけで、この作品では、表紙にもなっている栞子さんが探偵役、主人公でニートの危機にさらされている五浦大輔がワトソン役となっています。
実在する本が各話のタイトルになっているのが特徴で、それらの本をテーマにした事件やら何やらがあり、栞子さんが本の知識とミス・マープル顔負けの洞察力で解決していく、という話。

読んで思ったのは、シリーズ向けのうまい設定だなぁというのと、話の展開が割と早い段階で読めてしまう、ということ。
それだけの材料を読者に与えるフェアなミステリーとも言えますし、重要なのは個々の話ではなく、シリーズを通して各話の裏を流れる本流ということかもしれません。
また、注目すべきは栞子さんの本に対する膨大な知識で、つまりは著者の三上さんの知識なわけで、その深さと広さには、もう参りましたという感じです。1巻の話の一つがヴィノグラードフ・クジミン「論理学入門」だったり、2巻では漫画が出てきたり、守備範囲どれだけ広いんですか。小説家が実在の小説を題材にするのは、かなりのプレッシャーがあったんじゃないかと上から目線で勝手に想像していますが、そんなプレッシャーを感じさせない、小説として純粋に楽しめる作品じゃないかと思います。

ちなみに、今2巻まで読み終わったところですが、どちらも大好物な「余韻の残るハッピーエンド」でした。
2012/09/30(Sun) 21:35:11