Hatena::ブログ(Diary)

mizchi log

@mizchiの雑記帳

2011-11-07

不思議なダンジョン風マップ自動生成


参考にしたのはここ http://racanhack.sourceforge.jp/rhdoc/index.html

方針

上記の説明だけ読んでコード参考にしなかったので全然違う実装になった。

大きな空部屋を作って、部屋のクラスごとに担当する領域を持っておく。再帰構造で次の部屋の参照をもっとく。隣の部屋へのルートを書けば全部の部屋が繋がる。

コード


部屋と部屋をつなぐ部分を手抜きでやったので他の部屋跨いだりする。

{pow,sqrt,abs,random,max,min} = Math
class Room
  constructor:(@map,@depth, @ax,@ay)->
    @max_size = 4
    @next = null
    if @depth > 0
      @next = @split()

    if @ax[1]-@ax[0] < 13
      @rx = @ax
    else
      cx = ~~((@ax[0]+@ax[1])/2)
      @rx = [cx-6, cx+6]
    if @ay[1]-@ay[0] < 13
      @ry = @ay
    else
      cy = ~~((@ay[0]+@ay[1])/2)
      @ry = [cy-6, cy+6]

    @center = [
      ~~((@rx[1]+@rx[0])/2)
      ~~((@ry[1]+@ry[0])/2)
    ]

    @draw_area()

  _v : ->
    [sx , ex] = @ax
    cx = ~~( (ex-sx)*(max(0.2,1-random()/@depth) )+sx  )
    @ax = [cx,ex]
    new Room @map,--@depth, [sx,cx ],@ay

  _s : ->
    [sy , ey] = @ay
    cy = ~~( (ey-sy)*(1-random()/@depth)+sy  )
    @ay = [cy,ey]
    new Room @map,--@depth, @ax , [sy,cy]

  split:->
    if Math.random() > 0.5
      @_s()
    else
      @_v()

  draw_area : ->
    [sx,ex] = @rx
    [sy,ey] = @ry
    for i in [sx ... ex]
      for j in [sy ... ey]
        if @center[0] is i and @center[1] is j
          @map[i][j] = 2
          console.log i,j
        if (i == sx or i == (ex-1) ) or (j == sy or j == (ey-1))
          @map[i][j] = 1
        else
          @map[i][j] = 0

  draw_path : ->
    if @next
      [cx,cy] = @center
      [nx,ny] = @next.center
      while abs(cx-nx)+abs(cy-ny) > 0
        if cx>nx then cx--
        else if cx<nx then cx++
        else if cy>ny then cy--
        else if cy<ny then cy++
        @map[cx][cy] = 0
      @next.draw_path()

blank = (x,y)->
  map = []
  for i in [0 ... x]
    map[i] = []
    for j in [0 ... y]
      map[i][j] = 1
  return map

create_map = ->
  x = 30
  y = 30
  root = new Room(blank(x,y),13 ,[1,x-1],[1,y-1])
  root.draw_path()
  root.map

main = ->
  map = create_map()
  for i in map
    console.log i
      .join('')
      .split('0').join('  ')
      .split('1').join('//')
      .split('2').join('..')

main()


実行したらこんな感じ。

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////                    ////////////////////////////////////
////                    ////////////////////////////////////
////                    ////////////////////////////////////
//////////////  ////////////////////////////////////////////
//////////////  //////////////    ////    //////////////////
////                    //////    ////    //////////////////
////                    //////    ////    //////////////////
////                    //////    ////    //////////////////
////                    //////    ////    //////////////////
////                    ////                          //////
////                    ////      ////    //////////////////
////                    ////                              //
////                    ////      ////    //////////////  //
////                    ////      ////    //////////////  //
//////////////  ////////////      //////////////////////  //
//////////////  ////////////      //////////////////////  //
////                    ////      //////////////////////  //
//////////////  ////////////      //////////////////////  //
//////////////                    //////////////////////  //
////////////////////////////    ////////////////////////  //
////////////////////////////    ////////////////////////  //
////////////////////////////    ////////////////////////  //
//////////////////                                        //
//////////////////////////////  ////////////////////////////
//////////////////////////////  ////////////////////////////
//////////////////////////////  ////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

2011-08-13

Twitterの #自分の人生に影響を与えたゲーム3本 を集計してみた


昨日の夕方ぐらいから #自分の人生に影響を与えたゲーム3本 ってタグが流れてて、面白そうだったのでクロールして集計してみました。手持ちのレコードは2567件。

集計した、とは言っても、表記揺れが激しいので完全にカウントできたわけじゃないですが、
2500件あればある程度省かれることを考慮してもそこそこ妥当なデータだと思うので、もういいや(考えることをやめた)。

10票以上のもの



タイトル票数
ポケモン 134
クロノトリガー 38
ゼルダの伝説 38
FF6 33
ぷよぷよ 33
FF7 31
FF9 31
MOTHER2 30
MOTHER 29
FF5 28
大神 27
ゼノギアス 25
ドラクエ 25
Fate 24
スマブラ 24
東方 24
ポップン 24
サクラ大戦 24
FF4 23
PSO 23
逆転裁判 22
テイルズオブファンタジア 22
RO 22
幻想水滸伝 21
ハイドライド 21
FF11 21
モンスターハンター 20
FF 20
モンハン 20
月姫 20
女神転生 20
タクティクスオウガ 19
テイルズ 18
戦国BASARA 18
テイルズオブシンフォニア 18
DQ3 18
ドラクエ3 18
サモンナイト 17
ウィザードリィ 17
スーパーマリオブラザーズ 16
FF3 15
イース 15
ToHeart 15
キングダムハーツ 15
バイオハザード 15
メタルギアソリッド 14
MOTHER3 14
Kanon 14
FFT 14
ポップンミュージック 14
DQ5 14
スパロボ 13
ドラゴンクエスト 13
ソーサリアン 13
ラグナロクオンライン 13
マリオ 13
女神異聞録ペルソナ 13
.hack 13
牧場物語 13
ドラクエ5 13
スペースハリアー 12
ドルアーガの塔 12
テトリス 12
ときめきメモリアル 12
アイドルマスター 12
Wizardry 12
ポケットモンスター 12
ポケモン赤 11
アイマス 11
グラディウス 11
ファンタシースターオンライン 11
マザー2 11
MGS 11
ICO 11
ロックマン 11
beatmania 11
クロノクロス 11
風来のシレン 11
FF10 11
マリオブラザーズ 11

やっぱ90年代の後期のJRPG強いですね


以下、今回使用したスクリプト


集計 Python

#!/usr/bin/env python
# encoding:utf8
import pymongo
import re
db = pymongo.Connection()['twitter']['most_shocked_games']
print "count ",db.count()

res = {}
def push(item):
    if item in res : 
        res[item] += 1
    else :
        res[item] = 1

for i in db.find():
    text =  i["text"].replace(u"#自分の人生に影響を与えたゲーム3本","")
    text = re.sub( u'(\(|().*?(\)|)) ',u'',text )
    d = re.findall(u"(「|『).*?(」|』)",text)
    if len(d) >= 2:
        for t in d: 
            push( t ) 
    else:
        for t in re.split( u'・| |,|、| |/|/',text):
            push( t ) 


res = sorted(res.items(), key = lambda x:x[1] )
for k,v in res[::-1]:
    if v > 10:
        print k,v


クローラ nodejs

var TwitterNode = require('twitter-node').TwitterNode
,  sys = require('sys');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/twitter');
//コレクションのスキーマ
user_scheme = {
  name : String,
  text : String 
};
User = mongoose.model('most_shocked_games', new mongoose.Schema(user_scheme) );


var twit = new TwitterNode({
user: '"<username>',
password: '<password>',
track: ['#自分の人生に影響を与えたゲーム3本']
});

twit.addListener('error',  function(error) {
    console.log(error.message);
});

twit
.addListener('tweet',  function(tweet) {
    sys.puts("@" + tweet.user.screen_name + ": " + tweet.text);
    item = new User();
    item.name = tweet.user.screen_name;
    item.text = tweet.text;
    item.save(function(e){
        console.log('add new item:'+JSON.stringify(item));
});

})
.stream();
//要素の追加

それぞれのコード、書くのに15分もかかってないし、この記事書くのにそれと同じぐらいの時間使ってるので、コーディング速度上がってきた気がする。

2010-09-26

ポケモンBW感想 ネタバレあり


寝る間を惜しんでやってた。


小学三年生の頃にポケモンが流行った直撃世代なのだが、ルビー・サファイア以来のポケモン。
ダイヤモンド/パールは受験時代だったのでスルーしていた。

ストーリー


敵の組織は「ポケモンと人間の正しい共生」という壮大なテーマを掲げた割には、その回りの世界観が掘り下げられてないので共感も糞もないのだが、結局わかりやすい勧善懲悪にするためにゲーチスが完全悪を引き受けた格好。宗教色強め。子供向け、という縛りがなければ、もっと面白いものになったかもしれない。主となるプレーヤー層を考えるとここらへんが限界か。

と思ったら面白い記事をみつけた : S2workerS' web:ポケモンの神話 http://s2web.sokowonantoka.com/fromblog/pokemonmyth.html


Nの部屋はかなりキチガイじみている。Nを純粋な存在に仕立て上げるために、閉じた環境で洗脳されていたのだろう。部屋を走りまわるおもちゃの電車と、壁に突き刺さったナイフが狂気を演出している。


子供には伝わらりそうにない性的な想像を喚起させるフレーズを多用していて、そういう意味で大人向けファンサービスも悪くない。(保護者受けはしらん)
女性キャラのドットがこれでもかというほど完成度が高く、フェチズムが漂っている。

システム


難易度は若干高め。
鬼のようなバランス調整のあとが見える。とくにLv差による経験値補正は、ありがちだった高Lv単騎駆けをやりにくくし、複数モンスターを育てさせる方向に作用している。そしてクリア後の四天王戦での育成で、低Lvモンスターを育てるのを楽にしている。
配置トレーナーも、ダンジョン内で回復してくれるキャラの配置も絶妙。


ただ、エンカウント率が高すぎる。おそらくクリア後の低エンカウントモンスターや廃人向け努力値稼ぎに調整したのだろうが、ゲームをクリアするだけにしては異常なエンカウント設定のように思える。正直、方向転換でエンカウントとかFC時代までにしてほしい。

GTS


GTSというシステムでwifiを介して交換できるのだが、希望がレシラムゼクロスのパッケージの伝説ポケばかりで機能していない。なかには真っ当な希望もあるのだが、前者の圧倒的な比率によって埋もれてしまっている。そしてソート機能が貧弱だ。
これも年齢層的に仕方ないのだろうが... 伝説級のポケモンは伝説としか交換ができないようにするなどの解決策があったはずなのだが。

拭えぬ作業感


これは全シリーズに共通する、ガチ対戦向けの話なのだけど...


タマゴを孵化させて強いポケモンを作る、ということが、どうも受け付けられない。
個体値と言われるそのモンスター固有のパラメタがある。これはどんなに頑張っても生後変化しない。
オスメス二匹預けるとタマゴを生む。タマゴから産まれたポケモンは両親からHP こうげき ぼうぎょ とくしゅ とくぼう すばやさから三つの個体値を受け継ぐ。
さらには性格補正や努力値補正などがあり、どこで妥協するかなのだけど、ガチ対戦用のポケモンを一匹育てるのに環境を揃えるまでに20時間、そこから一匹育てるのに4~5時間程度かかる。


ここでどうしても違和感を覚える。
自転車で走り回るだけのタマゴ孵化作業と、対戦させることが全く別種で、前者はただの作業であり、後者はその作業を前提としたゲームのコアなのだが、ガチ対戦を楽しむのに前者の必要性が増していて、どうしても廃人ゲーになってしまうのだ。



今日は疲れたのでここらへんにして、明日以降に続く(かもしれない)