Symfoware

Symfowareについての考察blog

Mario AI Competition 穴を避けてジャンプする その1

まだAIとは呼べませんね・・・

Mario AI Competition を動かす
Mario AI Competition プログラムからマリオを操作する
Mario AI Competition 画面の情報を取得する
Mario AI Competition マリオをジャンプさせる


せめて、穴を避けてジャンプするようにしてみます。
作戦は、「自分より先に穴がある場合は、ジャンプを控える。」

また、ジャンプする方法に関して、改良を行いました。

1.地面にいるときジャンプする。
2.ジャンプ中、上昇している場合はジャンプボタンをずっと押しておく。
3.ジャンプ中、下降が始まった場合はジャンプボタンを離す。

マリオが上昇しているのかの判断ですが、
observation.getMarioFloatPos()
このメソッドの戻り値floatの2番目に、y軸方向の情報が入っています。
ここで判断しました。

余談ですが、observation.getLevelSceneObservation()で得られる
マップは、マリオと中心としたものです。
それに対し、observation.getMarioFloatPos()で得られるマリオの
座標は、マップ全体に対する絶対座標です。



ソースはこんな感じ。


package com.fc2.blog68.symfoware.agents.ai;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

import ch.idsia.ai.agents.Agent;
import ch.idsia.ai.agents.RegisterableAgent;
import ch.idsia.mario.engine.sprites.Mario;
import ch.idsia.mario.environments.Environment;

public class MyAgent extends RegisterableAgent implements Agent {

    private float maxMario = 0;
    private int jumpCounter = 0;

    public MyAgent() {
        super("MyAgent");
        reset();
        action[Mario.KEY_JUMP] = false;
    }

    public boolean[] getAction(Environment observation) {

        //画面情報
        byte[][] map = observation.getLevelSceneObservation();
        //マリオの位置
        float[] marioPos = observation.getMarioFloatPos();

        if (observation.isMarioOnGround()) {
            if (action[Mario.KEY_JUMP]) {
                if (jumpCounter < 2){
                    action[Mario.KEY_JUMP] = false;
                } else {
                    action[Mario.KEY_JUMP] = true;
                }
                jumpCounter++;
            } else {
                if(isJump(map)){
                    action[Mario.KEY_JUMP] = true;
                    maxMario = marioPos[1];
                    jumpCounter = 0;
                } else {
                    action[Mario.KEY_JUMP] = false;
                }
            }

        //ジャンプ中
        } else {
            if (marioPos[1] <= maxMario) {
                action[Mario.KEY_JUMP] = true;
                maxMario = marioPos[1];
            } else {
                action[Mario.KEY_JUMP] = false;
            }
            jumpCounter++;
        }
        action[Mario.KEY_RIGHT] = true;

        return action;
    }

    private boolean isJump(byte[][] map) {

        if (isHole(map,17)){
            return false;
        }
        /*
        if (isHole(map, 15)){
            return false;
        }
        */
        return true;
    }

    private boolean isHole(byte[][] map, int y) {

        for (int i = 9; i < map[0].length; i++) {
            if (map[i][y] != 0) {
                return false;
            }
        }

        return true;
    }
}




実行結果はこんな感じ。




結論から言うと、この作戦はうまくいきません・・・
マリオの先を固定値で見ているので、状況によってはジャンプできなくなったり、
高いところからのジャンプだと見事に穴にはまったり。

※ちなみに、このロジックで一回クリアできました。


やっぱり、ちゃんとマリオの軌道計算をやんないといけないのかな・・・






関連記事
  1. 2009/08/31(月) 18:21:58|
  2. 備忘録
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ