2016年8月31日水曜日

Ruby Warrior をやってみる(Level9)

はい、Ruby Warrior の Level9 です。

説明を意訳する

毎度の事ながら、説明文を意訳します。

Time to hone your skills and apply all of the abilities that you have
learned. Watch your back.

これまで学んだ全てのスキルを使って頑張って。
後ろの攻撃に注意。

こんな感じですかね。
先に書いてしまいますが、この Level9 で一旦のクリアになるようです。
なので、こういう文面になっているようです。

前レベルのコードをそのまま実行

これまで通り、前レベルクリアのコードをそのまま実行してみます。。。
見事にフルボッコにあって敵一人倒さずに終了してしまいました。さすが最終レベル。

さて、どうする?

開始直後に前後 3 マスに敵が配置されています。
そして、開始時点で戦士は右に向いています。
右の緑の敵は、目の前に行かないと攻撃してきませんが、後ろの弓持ちは、最初の位置からでも攻撃してきます。
ここの判定が難しいです。

攻撃された方向がメソッド等で取得できるのであれば良いのですが、ただダメージを貰ったという内容だけではどの方向に向けば良いか判定する方法が分かりませんでした。

なので、ここは説明文にあった忠告通り、最初は後ろを向いてそこからゲームをスタートする様にしました。
最初の向きを変える部分は、クラス変数を用意して最初の一度だけ方向を転換する実装としました。
ここの部分がちょっとかっこ悪いような気がしますが、勝てば官軍ということで。。。

さあ!反撃だ!?

初期の方向転換ができたので、早速攻撃を開始していきます。
弓持ちについては、開始位置からこちらも弓で攻撃すれば倒すことが出来ます。

しかし、その後前回のコードのままにすると、左に進み、捕虜を一人助けて、そのまま階段へすすみクリアしてしまいます。。。

どうやら、階段へ進みさえすればこのゲームはクリアとなるので、いいっちゃ良いんですが、右にも捕虜がいるので、全員助けてクリアしたい物です。

どうすれば良いか考えた所、汎用性は無い気がしますが、目の前の敵を倒した後に再度周り 3 マスを検索して敵がいれば方向を転換するようにしました。

これで、最初の位置で弓持ちを倒したら後ろを向いて緑の敵の方向を総なめし、壁にあたった所で向きを替え、最終的には階段へ向かうようになりました。

これがコードだ

class Player
  def initialize
    @health = 20
    @first_pivot = false
  end
  
  def play_turn(warrior)
    @warrior = warrior
    
    unless @first_pivot
      @first_pivot = true
      return warrior.pivot!
    end
    
    return warrior.pivot! if feel_wall?
    return warrior.rescue! if feel_captive?

    three_space_captive?

    if decrease_health?
      if pinch_health?
        warrior.walk!(:backward)
      else
        if check_enemy?
          warrior_attack!
        elsif three_space_enemy?
          warrior_pivot? ? warrior.pivot! : warrior_arrow_attack!
        else
          warrior_walk!
        end
      end
    else
      if max_health?
        if three_space_captive?
          warrior_walk!
        elsif three_space_enemy?
          warrior_pivot? ? warrior.pivot! : warrior_arrow_attack!
        else
          warrior_walk!
        end
      else
        warrior.rest!
      end
    end
    @health = warrior.health
  end
  
  def three_space_captive?
    spaces = @warrior.look
    spaces.each do |space|
      return true if space.captive?
    end
    false
  end

  def three_space_enemy?
    spaces = @warrior.look
    spaces.each do |space|
      return true if space.enemy?
    end
    spaces = @warrior.look(:backward)
    spaces.each do |space|
      return true if space.enemy?
    end
    false
  end
  
  def warrior_pivot?
    spaces = @warrior.look
    spaces.each do |space|
      return false if space.enemy?
    end
    spaces = @warrior.look(:backward)
    spaces.each do |space|
      return true if space.enemy?
    end
    false
  end

  def decrease_health?
    @health > @warrior.health
  end
  
  def pinch_pinch_health?
    @warrior.health <= 5
  end
  
  def pinch_health?
    @warrior.health <= 5
  end
  
  def max_health?
    @warrior.health == 20
  end
  
  def feel_captive?
    @warrior.feel.captive?
  end
  
  def feel_wall?
    @warrior.feel.wall?
  end
  
  def check_enemy?
    @warrior.feel.enemy? || @warrior.feel(:backward).enemy?
  end
  
  def warrior_walk!
    @warrior.walk!
  end

  def warrior_attack!
    @warrior.attack!
  end
  
  def warrior_arrow_attack!
    @warrior.shoot!
  end
end

まとめ

前にも書いたとおり、もっと汎用性をもたせれるのかもしれませんが、その都度の実装でなんとかクリアすることができました。
一旦更新を途絶えさせてからの再開でしたので、モチベーションが若干下がっていたのですが、一旦の区切りを付けることができ、良かったかと思っています。

あらたなレベルに進むかは決めていませんが、また余裕ができたらやってみたいと思います。それでは。

Written with StackEdit.

LAMY2000 ローラーボール

今回は、前回に引き続き、LAMY2000 のローラーボール版を紹介します。

万年筆と外観の比較

まずは外観です。

いつもどおりの LAMY2000 の形です。
どうです?万年筆と瓜二つの外観でしょ。
キャップも万年筆と同じ嵌合式となっています。

見分け方としては、キャップの上部にくぼみがある物がローラーボールとなります。
まあ、キャップを外せば一目瞭然ですけど。
それ以外はこれといった違いが無いので、並べられると正直分かりません。

ローラーボール版?

日本では万年筆や、4色ボールペンの記事をよく見ますね。
ローラーボール自体の紹介をあまりみないのは気のせいでしょうか。国内でローラーボールといえば、V コーンやエナージェルが評価が高ようです。

たしか海外では、ローラーボールが人気1 というのを何処かで読んだ気がするので、そこいらを汲みとってのラインナップになるのでしょうか。

不満点はローラーボールのインク

個人的な感想ですが、ローラーボールは、インク乗りがよいので、スラスラ書ける反面、手を止めると紙によっては、にじみが出てしまうのであまり好きではありません。

これ以外にも複数本のローラーボールを何度かチャレンジしたのですが、どうしてもにじみの部分でストレスが溜まってしまいました。

じゃあ、ボールペン版にすれば良いのに

知ってます。LAMY2000 にはボールペン版もあります。
これまた個人的な部分ですが、ノック式はペン先部分がでているのがどうも好きになれない2

なので、ペン先をしっかり守るキャップ式のボールペンの方が好きなのですが、文具店で見るボールペンは大半がノック式ですね。

なのでジェットストリームのインクを換装

と、言うことで、この界隈では当たり前!?のジェットストリーム換装をしてインク部分の不満を取り除くようにしました。

方法は、通常のノック式のジェットストリームを購入して分解。そして、分解した時に出るインクとバネを使います。
インクは、元のローラーボールのインクと同じサイズにするためおしり部分を切断。
バネは、切断して後ろの支えと、先にガタツキ防止に使用します。また、ペン先が若干ガタつくので、セロハンテープでガタツキを埋めます。

これで、ペン先の乾きや、手を止めた時のにじみを気にすることなく LAMY2000 の軸を楽しむことができました。

今では、こんなことをしなくても換装用の 4C が使える替えカートリッジが販売されているので、こちらを使ったほうが良いかもしれませんね。
ただ、4C サイズなのでインクの量などが気になる人は、この手の改造をした方がインク交換のスパンが長くなって良いかと思います。

まとめ

ジェットストリーム化にするには、ちょっとした手間がかかりますが、LAMY2000 のキャップ式が好きな人にはおすすめしたいと思います。
値段も万年筆と比較すると若干お手頃です。
なんちゃってですが万年筆の雰囲気を味わうにも良いかもしれません。
勝手にボールペン換装推しになっていますが、ローラーボールでも十分良い書き味なので、ローラーボール派にもおすすめです。
万年筆、ローラーボールと2 本揃えると統一感があっていい感じがします。パット見分からなくなりますけどね。

Written with StackEdit.


  1. 今はどうか知らないが。
  2. とか言いながら、ボールペン版に似た形状の uni の PURE MALT を購入している。

2016年8月29日月曜日

StackEdit の機能を最大限に使い blogger へ投稿

ブログを書く際に StackEdit を使用してるが、今ひとつ使いこなせていない気がしたので、再度機能の見直しをしてみると、有用な部分があったので紹介する。

今回見つけた機能は以下のとおり、
あと、説明上[]を全角にしているが、実際は半角で入力。

目次をつくる

次に、見出しを作る方法行の先頭に [toc] とつけると h1 等のタグを自動的に拾いリンクにしてくれる。
ただし、ページ全体の h1 タグをひらうので、途中にこの指定をしても、そこから以降にはならないので注意。

[toc]

↑こう書くとページの最初の様な目次が作成される。

注釈をつかう

ちょっとした自適感想などは、これまで () を使って表していたが、StackEdit の注釈機能を使うことにより、簡単に作成できる事がわかった。
書き方は、「[^xxx]」で注釈のリンクをつけ、「[^xxx]:」で説明を記述をすれば良い。

こんな感じにすれば良い[^footer説明]
[^footer説明]:こんな感じにする。

こんな感じにすれば良い1

コードをのせる

コードを載せたの時のシンタックスハイライトについては、これまでも実現していたが、簡易な方法として highlight.js を使用する方法があったので、これまでの物と合わせて使用するようにした2
使用にあたっては、blogger 自体に設定が必要とはなるが、それほど難しくはないので試してみる価値はあるかと思う。
凝った表示にしたいのであれば、ここから手をいれるか、別の方法を検討しないといけない。

設定は、blogger のメニューからテンプレート > ブログで使用中の HTML の編集をクリックし、header 部分に以下のコードを追加する。

<link href='//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/monokai-sublime.min.css' rel='stylesheet'/>
<script src='//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js'/>
<script>
    hljs.initHighlightingOnLoad();
</script>

これを設定したら、コードブロック(“`)を使用してプログラムコードを入れると、いい感じにコードが見やすく色づけされる。

```ruby
puts 'The best way to log and share programmers knowledge.'
hoge = Hoge.new
```

↑こうかくと
↓このように表示される

puts 'The best way to log and share programmers knowledge.'
hoge = Hoge.new

シーケンス図などものせる

なんと、StackEdit は、URL やシーケンス図を DSL を使って表現できる Sequence diagrams や about Flow charts 構文もサポートしている。
そして、そのまま blogger へ送る事もできる。
流石に、この手の図は StackEdit 上では表示可能だが、blogger へ転送するとテキストに置き換わるだろうと思っていが、きちんと表示されている。
このブログでは CSS の関係で見づらいが、これはすごいと思う。

使い方は、これまたコードブロックに sequence 指定をして、然るべき書式を使うだけ。

```sequence
WEBサーバ->DBサーバ: データ挿入
Note right of DBサーバ: DataBaseには\nユーザデータが\n格納される
DBサーバ-->WEBサーバ: データ参照
WEBサーバ->>DBサーバ: データ更新
```

↑こうかくと
↓このように表示される

Created with Raphaël 2.1.2WEBサーバWEBサーバDBサーバDBサーバデータ挿入DataBaseにはユーザデータが格納されるデータ参照データ更新

おまけ

これは、以前から使っていたけど、StackEdit を使ってそのまま、Upload したら公開されてしまうのが困る場合、やタグを入れたい場合は、ページの先頭に

---
tags: ["App"]
published: false
---

と記述しておくと、tag の指定と公開設定ができるので、おおまかな部分を StackEdit で書いてアップした後 blogger 側で調整することができる。

よく分からんこと

ここまででも十分なんだけど、実際のブログと見た目が違う点が少し残念。
StackEdit 内で CSS を設定したいがどこで設定したら良いかわからない。

まとめ

StackEdit の見直しをして、欲しかった目次つくる機能などを発見できたのは、すごく良かった。
通常の Markdown は対応しているし、まさかシーケンス図とうの図までそのまま送れるとは思わなかった。
これは blog を書く人は StackEdit を使わないと損するかもしれない。

Written with StackEdit.


  1. こんな感じにする。
  2. そのままでは、行番号を表示しないから併用するようにした。

2016年8月28日日曜日

Ruby Warrior をやってみる(Level8)

Ruby Warrior Level8 です。

説明部分意訳します。

You hear the mumbling of wizards. Beware of their deadly wands! Good
thing you found a bow. Use warrior.look to determine your
surroundings, and warrior.shoot! to fire an arrow.

魔術師が詠唱をしている声が聞こえます。
彼らは広範囲の致命攻撃をして来るので注意してください。
幸運にも、弓矢を発見しました。
warrior.look メソッドにより環境を確認して warrior.shoot! で矢を放ってください。

ですかね。

と、言うわけで新しいメソッドが 2 つ増えました。
warrior.look メソッドは、前方 3 マス分の SPACE オブジェクトを配列の形で取得できるメソッドです。
このメソッドを使うことではターンを消費しないので、このメソッドの後に、移動や攻撃のメソッドを呼ぶことが出来ます。

もう一つは、warrior.shoot! メソッド。
どうやら弓矢を手に入れたらしいので、これを使う事により遠距離攻撃ができるようになります。
このメソッドは、通常の攻撃同様 1 ターン消費します。

これらを駆使してクリアを目指します。

まず、恒例の前回のソースそのまま実行の結果ですが、捕虜を助けた後に魔法使いの無慈悲な攻撃を受けます。その後1体は倒すのですが、次ターンでオーバキルされてしまいました。
やはり、上記のメソッドを駆使するしかなさそうです。

一番楽なのは、look メソッドを使わずに、shoot! をした次のターンで一歩進むという方式を取れば良いのですが、これでは捕虜ものとも倒して進むといった非常な戦士になってしまいます。

で、これらを考慮したコードが以下のとおり。

class Player
  def initialize
    @health = 20
  end
  
  def play_turn(warrior)
    @warrior = warrior
    
    return warrior.pivot! if feel_wall?
    return warrior.rescue! if feel_captive?

    three_space_captive?

    if decrease_health?
      if pinch_health?
        warrior.walk!(:backward)
      else
        check_enemy? ? warrior_attack! : warrior_walk!
      end
    else
      if max_health?
        if three_space_captive?
          warrior_walk!
        elsif three_space_enemy?
          warrior_arrow_attack!
        else
          warrior_walk!
        end
      else
        warrior.rest!
      end
    end
    @health = warrior.health
  end
  
  def three_space_captive?
    spaces = @warrior.look
    spaces.each do |space|
      return true if space.captive?
    end
    false
  end

  def three_space_enemy?
    spaces = @warrior.look
    spaces.each do |space|
      return true if space.enemy?
    end
    false
  end

  def decrease_health?
    @health > @warrior.health
  end
  
  def pinch_pinch_health?
    @warrior.health <= 5
  end
  
  def pinch_health?
    @warrior.health <= 5
  end
  
  def max_health?
    @warrior.health == 20
  end
  
  def feel_captive?
    @warrior.feel.captive?
  end
  
  def feel_wall?
    @warrior.feel.wall?
  end
  
  def check_enemy?
    @warrior.feel.enemy? || @warrior.feel(:backward).enemy?
  end
  
  def warrior_walk!
    @warrior.walk!
  end

  def warrior_attack!
    @warrior.attack!
  end
  
  def warrior_arrow_attack!
    @warrior.shoot!
  end
end

look メソッドを使って、前方 3 マスの SPACE オブジェクトを取得して、その中に捕虜が居るか確認して、居た場合は前方に進み救出に専念し、捕虜がおらず敵が居るのであれば、弓で攻撃するようにしました。

これで、このレベルではなんとかうまくいきました。
ダメージ受けた時の処理はそのままなので、その部分が次のレベルで出てくると、ちょっと面倒だなと。

ということで、今日はこれまで。

Written with StackEdit.

LAMY2000 万年筆

手持ち文具紹介として、LAMY2000 系統をたくさん持っているので(過去に買いまくった。。。)、紹介していきます。

まずは、LAMY2000 の万年筆です。
何本か持っている万年筆の中でも割りと遅めに購入した物となります。

購入前の評判では、値段の割に使い勝手が良い。
カートリッジではなく、吸引型を採用している。
なにより軸の形が持ちやすいため、手に馴染み易い。
ペン先が柔らかい。
ということでした。
欠点として、インク漏れが有ったらしいのですが、新しい機構を採用してからはその問題も解消されているようです。

ここら辺の情報を仕入れたうえで購入をしました。
文具店で購入すると、ちょっと値が張りますので、Amazon にて購入しました。

万年筆は、あまり通販で買わないほうが良いとの事も聞きますが、近くの店舗に無かったり、金額との天秤にかけるとどうしても通販での購入となってしまいます。
この点を考えると、ちゃんとした店舗で万年筆を買うのは大人の嗜みなのかもしれません(自分は結構おっさんですが。。。)。

それはそうと、外装です。

LAMYの外箱は購入する年代によってかわるので、そこら辺も購入の楽しみになります。

次に、開けた所。

中には説明書と本体が入っています。
ビニール袋に包まれています。

そして、取り出した所。

ちょっと写真が白飛びしていますが、LAMY2000 特有の丸みを帯びた形と、軸のヘアライン加工となっています。
軸のおしりの方に、インク吸入の時に使う尻軸との切れ目が確認できます。パット見は気づきにくく、見事に一体感を醸し出しています。

キャップは嵌合式(パチンと閉まるタイプ)です。
嵌合式の方がデザイン的にも一体感が出るのでこの方式にしたのかもしれません。
最初のうちは、キャップ部にある乾燥防止の

万年筆で筆記の際にキャップを付ける派、付けない派があるかと思いますが、この万年筆の場合は付けたほうがバランス的に良い感じがします。

先端の方に目をやると、インク確認窓があることが分かります。
半透明の窓ですが、実用に問題ないかと思います。
また、尻軸同様、ペン先交換の際に使用する首軸部分の切れ目が確認できます。

ペン先部分の形状は独特でペンの必要部分だけが露出しているようになっています。この形状ならペン先固くなるのでは?と思いましたが、問題無いようです(この点については後述)。
そして、ペンの後ろに空気を取り入れる穴が開いています。
このバージョンでは一体化されていますが、この部分が古いバージョンのものだと別パーツになっていて、インク漏れを起こしやすくしていた原因だったようです。

実際に使用した間隔ですが、これまでに書いたとおり、手に取ると形的にも非常に温かみがあり手に馴染みます。
また、少々軽く感じますが、手軽に使用する万年筆ならかえってこの軽さが良い気がします。

ペン先が柔らかいとの評価がありますが、自分では分かりませんでした。
というのは、自分が購入する万年筆(数本持っていますが)は基本的に EF ですので、この柔らかいという表現がつかみにくいのかもしれません。

総合的に判断すると、手に馴染むこともあり普段使いの万年筆には良いかと思います。
LAMY2000 系統は統一感のある形なので、シリーズ物を持っているのであれば、満足の行く一品です。

形状が独特なので、この万年筆から他の万年筆や、他の万年筆からこの万年筆を使うなど行き来した時には、いい意味で変わった気持ちで文字を書けるかと思います。
初めての万年筆にも良いし、他の万年筆からの買い増しでも満足できる不思議な万年筆。

おひとついかがですか。

EF(極細字)
F(細字)
M(中字)
OM(傾斜付中字)
B(太字)
OB(傾斜付太字)
BB(極太字)

Written with StackEdit.

2016年8月22日月曜日

Chrome について色々

Google カレンダーに絡んだ仕事をしている時に気になったのだが、アドレスバーの横に菱型が重なったマークが表示されていた。

マウスポインタを重ねてみると、以下のように「このページはサービスハンドラのインストールを求めています。」と表示され、クリックすると、さらに「すべてのウェブカレンダーリンクを calendar.google.com で開きますか?」と選択肢が出てくる。

ハッキリ言って、なんのこっちゃよく分からない。
調べてみてもいまいち的を得ないものばかり。

それでも、なんとなくの理解だと、カレンダー関連(日付とか?)をクリックしたら Google カレンダーに遷移して開く動きとなるような事だろうか?

ハンドラの設定の管理… のボタンを押してもよくわからないし、とりあえず、何もせずに放置した。
何かしらの設定をしたら、Chrome の設定画面から「設定」→「詳細設定を表示」→プライバシーの「コンテンツの設定...」→ハンドラの「ハンドラを管理...」から何かしらの設定変更が出来るようだ。
しっかし、こういう点が Google 不親切だなぁ。

あと、Chrome アプリが 2018 年までに終了とのこと。

http://blog.chromium.org/2016/08/from-chrome-apps-to-web.html

Chrome OS での提供は続けられるとのことだが、どれだけの人が Chrome OS をつかっているのだろうか。。。

利用ユーザ数が少なくなっている事が終了の要因か。
とはいえ、この記事自体 Chrome アプリの StackEdit を使って書いている。ちょっと残念。

開発者目線でいくと、シェアの少ないアプリのサポートが減るのはちょっと気が楽になるが、なくなると思うとちょっとさびしい気持ちになるかもしれない。

Written with StackEdit.

Ruby Warrior をやってみる(Level7-2)

はい、今回は前回の続きで Level7 の pivot! メソッドを使ったバージョンです。

説明文は前回と同じなので、省略と。

今回は、しつこいようですが pivot! メソッドを使用する形になります。
pivot! メソッドは、戦士の向いている方向を変更するメソッドになります。
前回の :backward と違って、pivot! は破壊的メソッドのため(!マークが付いているからね)、これだけで 1 ターン使うので、pivot! の後に、warrior 系のメソッドを使うとエラーになってしまいます。
(ここいらのルール無視するとずっと俺のターンができるからしょうがないね)

ここで分かったのは、:backward 付きの攻撃と、敵と正面向いての攻撃とで与えるポイントが違う点。なんと細かいのだ。

なので、前回のような体力低下による戦略的撤退を最初の敵で行う必要がなくなります。
が、結局弓矢持ちの敵の所で、引く処理が必要なので、まあよく考えられているゲームになっています。

で、実装した結果が以下のとおり

class Player
  def initialize
    @health = 20
  end
  
  def play_turn(warrior)
    @warrior = warrior
    
    return warrior.pivot! if feel_wall?
    return warrior.rescue! if feel_captive?

    if decrease_health?
      if pinch_health?
        warrior.walk!(:backward)
      else
        check_enemy? ? warrior_attack! : warrior_walk!
      end
    else
      if max_health?
        check_enemy? ? warrior_attack! : warrior_walk!
      else
        warrior.rest!
      end
    end
    @health = warrior.health
  end
  
  def decrease_health?
    @health > @warrior.health
  end
  
  def pinch_health?
    @warrior.health <= 5
  end
  
  def max_health?
    @warrior.health == 20
  end
  
  def feel_captive?
    @warrior.feel.captive?
  end
  
  def feel_wall?
    @warrior.feel.wall?
  end
  
  def check_enemy?
    @warrior.feel.enemy? || @warrior.feel(:backward).enemy?
  end
  
  def warrior_walk!
    @warrior.walk!
  end

  def warrior_attack!
    @warrior.attack!
  end
end

前回の方向をインスタンス変数に持つのをやめて、壁がある場合には、pivot! メソッドを使って向きを変える処理の追加と、ピンチの場合の判断体力と、後ろに下がる処理を :backward 付きの処理に変更したぐらい。
各動作については、メソッドラップの必要性がなくなったけど、あえて残しています(面倒くさかった)。

毎度のことながら、ひとまずクリア出来たので、めでたしめでたしと。

Written with StackEdit.

Ruby Warrior をやってみる(Level7-1)

さて、今回は Level7 です。
だいぶんしんどくなってきた。。。

とはいえ、blog を書く気になっている間にやってしまわないとまた時間経ちそうなのでやってしまわないと。

前置きは良いとして、説明文を意訳します。

You feel a wall right in front of you and an opening behind you. You
are not as effective at attacking backward. Use warrior.feel.wall? and
warrior.pivot! to turn around.

壁を目の前にして開始します。
通常の攻撃は、後ろに対して行えません。
warrior.feel.wall? メソッドと warrior.pivot! メソッドを使って向きを変えてください。

かな?
前回、:backward メソッドを使用して後ろ側への移動などを行って来ましたが、今回からなんと! warrior.pivot! メソッドを使うと戦士の向きを変えることができるようになるそうです。

ってか、最初から教えておいてくれたらよかったのに。
ということで、前回の資産を活かせるか試してみたところ、当然うまく行きませんでした。しかし、pivot! を使わずに :backward 引数だけで対応できるのでは無いかと、ちょっと弄るとクリア出来たので、今回はそのコードを載せておきます。
次の回で、実際に pivot! を使った内容を実装します。

コードは以下のとおり

class Player
  def initialize
    @health = 20
    @direction = :backward
  end
  
  def play_turn(warrior)
    @warrior = warrior
    
    return warrior.rescue!(@direction) if feel_captive?
    @direction = change_direction if feel_wall?
    
    if decrease_health?
      if pinch_pinch_health?
        @direction = change_direction
        warrior_walk!
      else
        check_enemy? ? warrior_attack! : warrior_walk!
      end
      @direction = change_direction if pinch_health?
    else
      if max_health?
        check_enemy? ? warrior_attack! : warrior_walk!
      else
        warrior.rest!
      end
    end
    @health = warrior.health
  end
  
  def decrease_health?
    @health > @warrior.health
  end
  
  def pinch_pinch_health?
    @warrior.health <= 2
  end
  
  def pinch_health?
    @warrior.health <= 3
  end
  
  def max_health?
    @warrior.health == 20
  end
  
  def feel_captive?
    @warrior.feel(@direction).captive?
  end
  
  def feel_wall?
    @warrior.feel(@direction).wall?
  end
  
  def check_enemy?
    @warrior.feel.enemy? || @warrior.feel(:backward).enemy?
  end
  
  def warrior_walk!
    @warrior.walk!(@direction)
  end

  def warrior_attack!
    @warrior.attack!(@direction)
  end
  
  def change_direction
    @direction === :forward ? :backward : :forward
  end
end

今回だけの無理やりコードなので、攻撃にも方向シンボルの指定とメソッド化、ピンチ体力の調整、そして本格的にやばくなった時の動作を無理やり実装しています。

本格的にやばくなった時のコードが何故必要になったかというと、最初の緑の敵ですが、フル体力で殴りあっても勝てないようになっています。。。一旦退いて体力回復後殴らないと勝てない。なんて糞仕様素敵な的なんだ。

一応これで、なんとかクリアできます。
ちょっと無理やりですかね。まあ、本番は次回になるので良いとしましょうか。

Written with StackEdit.

2016年8月20日土曜日

システム手帳のリフィルの保管方法

ほぼ日手帳 2017 がそろそろ発売されますね。

それはそうと本屋に行くと、「システム手帳 STYLE(エイムック 3461)」が並んでいた。

以前は、システム手帳でフランクリン・プランナーを使っていたが、少々費用がかかる面などもあり、ほぼ日手帳 weeks に移行したが、割合うまくいっているので、遠ざかっていた。

でも、本を見ると手にしてしまう。
システム手帳のバンダーなんて一度買ってしまうと、そうそう替えないから参考程度とペラペラとページをめくっていたが、その中で使い終わったリフィルの保管方法について書いてあるページがあった。

中には、保管用バインダーを使う方法や製本する方法なども有ったが、やはりバインダーを購入して年ごとに保管する方がよさそうだ。
しかし、ちょっと高い。
100 円ショップにあるバインダーでもとは思ったが、多分年ごとに外見が変わるので、保管には向いていないかと。

調べてみると手頃な価格のものがあったので、これでも使ってみようと思う。

Written with StackEdit.

atom の split-diff パッケージが便利

Windows PC から Mac に変わってから、暫く経ち、ようやく違和感無しに使えるようになってきた。
主に仕事の開発で使っているということもあるとは思う。

その中で、どうしても不便な点が文字列比較だった。
Windows には WinMarge という、手軽に扱え高性能といったソフトが有ったが、Mac には類似ソフトが無くて困っていた。

唯一近い物が TextWrangler だと思うが、基本エディタで比較を行うには、一旦ファイルに保存してから比較をする動作となっていた(最近触っていないので変わっているかも)。

TextWrangler
https://itunes.apple.com/jp/app/textwrangler/id404010395?mt=12

ファイル保存等は不要で文字列比較出来る方法無いかなと思っていたら、atom エディタの パッケージに split-diff というものがあることを知った。

このパッケージを入れ、メニューの Packages から split-diff を選択すると、画面が左右に分割される。
あとは、比較したい文字列を左右に貼り付ければ、差異のある部分が赤くなり確認できる。

なんと素晴らしい。
これで、ますます WIndows の環境に未練を残さなくなった。
これだけの機能だが、文字列比較で困っていたは人は使ってみてはどうでしょう。

Written with StackEdit.

Ruby Warrior をやってみる(Level6)

はい。また Ruby Warrior です。
前回に引き続き Level6 です。

だんだん難しくなってきました。
例によって、説明文を意訳します。

The wall behind you feels a bit further away in this room. And you
hear more cries for help. You can walk backward by passing ‘:backward’
as an argument to walk!. Same goes for feel, rescue! and attack!.
Archers have a limited attack distance.

背後に壁があるのを感じる。
そして、助けを求める声も聞こえる。
:backward を walk! に引数にすることで後退することができる。
これを使って感じ取り、捕虜を助け、そして敵を攻撃せよ。
ここにいるアーチャーは範囲攻撃を持っている。

って感じですかね。
どうやら feel 系(warrior.feel(:backward).xxx)のメソッドの引数や、warrior のメソッド(e.g. warrior.walk!(:backward) など)に :backward シンボルを渡すことで、戦士の背後のチェックや行動ができるようになるみたいです。
ちなみに、:backward の反対は :forward を使うこともできます。
ココらへんは、デフォルト引数(xxx(direction=:forward)みたいな感じ)でも使ってるんでしょうか。

さて、ここいら辺の情報を持ってしても適当に実装するとクリアできませんでした。
相変わらずロジックがショボイからでしょうか。
悲観的なことは置いていて、クリアしたコードは以下のとおり。

class Player
  def initialize
    @health = 20
    @direction = :backward
  end
  
  def play_turn(warrior)
    @warrior = warrior

    return warrior.rescue!(@direction) if feel_captive?
    @direction = change_direction if feel_wall?

    if decrease_health?
      check_enemy? ? warrior.attack! : warrior_walk!
      @direction = change_direction if pinch_health?
    else
      if max_health?
        check_enemy? ? warrior.attack! : warrior_walk!
      else
        warrior.rest!
      end
    end
    @health = warrior.health
  end
  
  def decrease_health?
    @health > @warrior.health
  end
  
  def pinch_health?
    @warrior.health <= 8
  end
  
  def max_health?
    @warrior.health == 20
  end
  
  def feel_captive?
    @warrior.feel(@direction).captive?
  end
  
  def feel_wall?
    @warrior.feel(@direction).wall?
  end
  
  def check_enemy?
    @warrior.feel.enemy? || @warrior.feel(:backward).enemy?
  end
  
  def warrior_walk!
    @warrior.walk!(@direction)
  end
  
  def change_direction
    @direction === :forward ? :backward : :forward
  end
end

デフォルトである「# cool code goes here」のコメントはクールなコードな気分がなんとなくしなくなったので外しました。

説明文にあったとおり、このレベルから方向を指定できるようになったので、方向を保持するインスタンス変数を使うようにしました。これ使って救助や攻撃、移動の方向を指定するようにします。

あと、if 文が多用に使われて見難いので判定系はメソッドに分けてみました。メソッド化に当たり、play_turn() の warrior を各メソッドの引数で渡そうかとも思いましたが、ゲーム内だけなので、これもインスタンス変数を用いるようにしました。

終盤のアーチャー 2 体部分がいやらしいのですが、攻撃を一定量もらうと攻撃の当たらない位置まで一旦退いて回復後出直す方法をとっています。

うーん。今回は、敵の配置等を見て、このレベル専用に実装したんですが、これ汎用的な実装できるんでしょうか?
終わったら他の人のコードも見てみましょうか。。。

Written with StackEdit.

2016年8月18日木曜日

Ruby Warrior をやってみる(Level5)

はい、今回は Level5 です。
これまで同様に内容を意訳してみます。

You hear cries for help. Captives must need rescuing. Use
warrior.feel.captive? to see if there is a captive and warrior.rescue!
to rescue him. Don’t attack captives.

捕虜が助けを呼んでいる。
warrior.feel.captiove? メソッドで捕虜の存在を確認して、warrior.rescue! メソッドで捕虜を助けてください。
捕虜を攻撃しちゃダメ。

とのこと。
檻に入って不安そうな感じの目をしているのが捕虜のようです。
見た目が悪いのでゲームがゲームならミミック系の敵で倒してしまいそう。。。

そんな話は置いといて、今回も説明文にあるとおり、新しいメソッドを使って捕虜を助けつつ攻略していく形になります。

前回のそのまま起動したけど、捕虜の檻で足踏みして先に進まないので、改良が必要ですね(当たり前だけど)。

手っ取り早く、捕虜救出の部分だけを書いて実行すると、最後の緑の敵であっさり倒されてしまいます。

具体的には敵を倒した後に、次のターンで前進してしまい、そこにまた敵がいるので、殴り合いの末 K.O されるようになっていました。

で、色々模索してコードをすっきりさせる方法を探ってみたのですが、結果ぐちゃぐちゃに。
ひとまず、クリアはできたのでコード載せておきます。


class Player
  def initialize
    @health = 20
    @damage = false
  end
  
  def play_turn(warrior)
    # cool code goes here
    return warrior.rescue! if warrior.feel.captive?

    if @health > warrior.health
      if @damage
        warrior.feel.enemy? ? warrior.attack! : warrior.walk!
      else
        warrior.feel.enemy? ? warrior.attack! : warrior.rest!
      end
      @damage = true
    else
      if warrior.health <= 12
        warrior.rest!
      else
        warrior.feel.enemy? ? warrior.attack! : warrior.walk!
      end
      @damage = false
    end
    @health = warrior.health
  end
end

かっちょ悪いですが、@damage というインスタンス変数を設け、体力低下確認に合わせて 1 回だけは攻撃を踏ん張るようにしてみました。
これで、敵を倒した直ぐに前に進まず回復をするようになりクリアできます。

あんだけ if のネストが気持ち悪いと書いていたのにさらにネストがパワーアップしている。。。

Written with StackEdit.

2016年8月17日水曜日

Ruby Warrior をやってみる(Level4)

さて今回は、Level4 です。

You can hear bow strings being stretched. No new abilities this time,
but you must be careful not to rest while taking damage. Save a
@health instance variable and compare it on each turn to see if you’re
taking damage.

説明文を読むと、弓持ちの敵がいるので注意と言うことと、ダメージを受けている時に回復したらアカンということ。これを判断するには @health インスタンス変数を使用しろということのようです。

明らかに弓を持ったおっさんと、でかくなった敵がいます。
前回のコードをそのまま実行しましたが、最後の敵でやられてしまいました。普通に考えたら成功するわけないですよね。。。

と、言うことで説明に有ったとおり @health インスタンス変数を使用してダメージを受けているかを判定して処理を分岐するようにします。

@health のインスタンス変数については最初は定義されていないので、どこかで定義をする必要があるのでとりあえず、Player クラスの initialize メソッドで定義するようにします。
その後は、play_turn() メソッドの最後の部分でターン終了時の戦士の体力を代入するようにします。

これで、自分のターン後に敵からダメージを受けていた場合、先程保持した値よりも戦士の体力が減っていればダメージを受けているかどうか判断がつくようになります。

ダメージを受けている場合は、のんきに回復などをしていると、消耗戦でやられてしまうので、さっさ前に進み敵を倒しに行くようにします。

ダメージに変動がなくなり、前方に敵がいない場合に限り回復処理を行うようにします。

ここで、回復のポイント数ですが、緑の敵がでかくなって5ターンの攻撃を行う必要があるので前回の回復目安 6pt ではやられてしまうため、4 ターン分耐え切る体力(3 x 4 = 12 以上)を確保するようにします。

これを踏まえて実装したコードが以下のようになります。

class Player
  def initialize
    @health = 20
  end
  
  def play_turn(warrior)
    # cool code goes here
    return warrior.attack! if warrior.feel.enemy?
    if @health > warrior.health
      warrior.walk!
    else
      if warrior.health <= 12
        warrior.rest!
      else
        warrior.feel.enemy? ? warrior.attack! : warrior.walk!
      end
    end
    @health = warrior.health
  end
end

if 文のネストが増えているのがちょっと嫌な感じですが、ひとまずクリアはできました。

2016年8月16日火曜日

Ruby Warrior をやってみる(Level3)

大分放置してた。。。
さて、Level3 です。

ここでは、敵の数が増えるので、今まで通りに進むと体力が足りずに詰みます。

説明文を読むと

The air feels thicker than before. There must be a horde of sludge.
Be careful not to die! Use warrior.health to keep an eye on your health, and warrior.rest! to earn 10% of max health back. 

warrior.health メソッドと warrior.rest! メソッドがキーと書いています。

warrior.health メソッドは、自分の体力を確認できるメソッドで、warrior.rest! メソッドが 体力最大の 10% を回復するメソッドになります。

こちらの攻撃が 1 回に付き 5 を与えて、3 ターンで倒せるので、体力は 15 ぐらいで、相手の攻撃で -3 をもらい、倒しきるまでに 2 ターンあるので、体力的には 6 より多くないと厳しいということになります。

ということで、必要条件の体力が 6 より小さくなった場合に、rest! メソッドで体力を回復させるようにします。

class Player
  def play_turn(warrior)
    # cool code goes here
    return warrior.rest! if warrior.health <= 6
    warrior.feel.enemy? ? warrior.attack! : warrior.walk!
  end
end

で、単純に体力確保だけを考えて実装後に実行をすると、途中で敵が 2 連続の部分でやられてしまいました。

具体的には、2 匹目の部分で、体力低下により回復(2pt)するけど、相手の攻撃(3pt)をもらい、消耗戦の結果、体力尽きてゲームーオーバーというパターンです。

これを回避するには、ゲームオーバー時に表示されるヒントをみると、

敵が目の前にいない時に回復するようにしろ!と書いてあります。
敵が目の前かどうかは、SPACES オブジェクトの enemy? メソッドを使えば判断できます。
space 系のオブジェクトは、warrior.feel から取得できるようになっているので、warrior.feel.enemy? と記述すれば判断が付きそうです。
最終的には、以下のようになりました。

class Player
  def play_turn(warrior)
    # cool code goes here
    return warrior.attack! if warrior.feel.enemy?
    return warrior.rest! if warrior.health <= 6
    warrior.feel.enemy? ? warrior.attack! : warrior.walk!
  end
end

うーんいい感じ

2016年8月15日月曜日

ミドリ グラスルーラー紹介(Amazon アソシエイトを使ってみる)

今回は、Amazon のアソシエイトを使ってみることを名目に商品の紹介をします。

Designphil Design Project - Glass Ruler
http://www.designphil.co.jp/designphilcollection/products/glass_ruler.html

かなり前から Amazon のアソシエイトには登録していたのだが、blogger の アドセンスと共存してよかった物かわからなかったので、使っていなかったけど、なんとなく両方使って問題なさそうなので使ってみます。
以下に、ミドリのグラスルーラーのリンクを貼ってみます。

多分出ているかな。。。

さて、この商品は見ての通り定規なんですけど、強化ガラスを使用した定規となっており、非常に見た目が美しくなっています。
ただ、無駄に重く、雑に扱うと割れそうなので気持ちに余裕がないとちょっと厳しい商品となっています。
また、付属で専用ケースが付いています(肌触りとしてはスエードっぽい)。
このケースも結構タイトに作ってあるので、出し入れの時に結構な抵抗があります。
使い続ければ慣れてくるかと思うので、暫く様子見ということで。

定規にしては、かなり高価なものにはなりますが、定規なんてそうそう買い換えるものではないので(用途によりますが)、年齢的にも多分最後の定規なんじゃないかと。
まあ、ガラスなんで割れたら別ですけど、その時も多分これを買うでしょう。
それくらい魅力のある商品です。

頻繁に使うものでもないけど、使うときに少しうれしい感じがいいので、大人の文具といった感じでしょうか。
気になった方お一ついかがですか?

Rails に慣れる方法

Rails を使うようになった。
まだまだ使いこなせている感が出ていないけど、Rails に関しては全くの白紙の状態から今の段階まで早く到達する方法を自分なりにメモって置きます。

大きく分けると以下の 3 つ

  1. 大量に情報を詰め込む
  2. Ruby 自体を理解する
  3. 利用できる gem を知っておく

1. 大量に情報を詰め込む

Rails ぐらいになると、Web には山のように情報がある。
当然これを活用しても良いが、まずは書籍を数冊購入し読み漁る(この手の本は無駄に高いので会社で購入か持っている人に借りるかをした方がよい)。

なぜ書籍なのかというのは、書籍の場合は使用している Ruby や Rails のバージョンが固定されているので、少々分からなくても次々とすすめることが出来る点が良い。

悪い点は、最新の情報に対応していない場合や、もっと言えば使用している API 側でバージョンが変わってしまって本の通りにプログラミングしても動かなくなってしまう可能性がある点。

話が若干それたが、書籍である程度の知識を得る。
その後、動画や Web 記事などを見るとそこに書かれてある内容が把握しし易い。

結局、出てくる語彙をいくら知っているかが肝で、Web の記事などを読んでいて、? マークが出た時に調べていたら本筋に戻れなくなってしまうのでそれをやらないためにも事前知識を蓄えておこうと言うことです。

自分なりに良かった媒体を下記に記します。

2. Ruby 自体を理解する

Rails は結局 Ruby を使っているので(なんか言い方悪い気がする)、本体の Ruby を理解しないとデバックの時に困るし、そもそもロジックが記述できないので本質的な部分を抑えましょうという話。

上記の書籍類には大体 Ruby の説明箇所がとられているので、本を読む時にはそれほど Ruby を感じる事はないけど、実際に自分で製品を作る段階に牙を剥いてくるので知識を得ときましょうという話。
Rails のエラーが出た時にも知識の有無でデバッグのスピードが異なる。

3. 利用できる gem を知っておく

Ruby の原則(?)として車輪の再発明はしないというものがある。
ちょっと小慣れてくるとどうしてもロジックを書きたくなるものだが、実はその時間が無駄だったり(頭ごなしに無駄とは思っていませんよ)、より良い物が世の中にはあったりする。
これらは、gem というもので提供されているので、まずは gem を探してからなければ実装とすればグッと開発時間が短縮できる可能性があるという話。

欠点としては、gem 自体に問題が有った場合。
知識がないと採用/不採用の判定や、修正ができる/できないが判断できない点。
まわりに、聞ける人がいれば良いんだけどね。


以上がざっと Rails の習得の時に過去の自分に会えるなら伝えたい内容です。
あとこれ以外なら開発環境は IDE を使ったほうが良いというぐらいかな。

ただ、Rails と言わず Web サービスを作るにあたっては、サーバーサイドだけでなく、HTML や CSS、JavaScript などのクライアントサイドや、サービスAPI に関する事や、サーバー自体の環境に関することなどもあるので一筋縄には行かない。

ちょっとした内容を読むには、英語も必要だし、込み入ったサービスなら仕様自体の理解も必要と考えるだけで、ちょっとしんどかったりもする。

とはいえ、チームで開発すると思うのでその部分は助け合いながら開発できれば良いかな。。。
(コミュ障気味な自分には厳しいなぁw)

Written with StackEdit.