Pre-release
Adventure.js Docs Downloads
Score: 0 Moves: 0
// selectReachableIfTangible.js

(function() {
  /*global adventurejs A*/ 
  "use strict";

	var p = adventurejs.Parser.prototype;

  /**
   * Exclude from a list of assets all assets that are not reachable by player.
   * @method adventurejs.Parser#selectReachableIfTangible
   * @memberOf adventurejs.Parser
   * @param {Array} list 
   * @returns {Array}
   */
   p.selectReachableIfTangible = function Parser_selectReachableIfTangible(list) 
  {
    if("string" === typeof list) list = [list];
		if( !Array.isArray( list ) ) 
    {
      this.game.log( "warn", "critical", "selectReachableIfTangible.js > received non-array", 'Parser' );
			return [];
    }

    var player = this.game.getPlayer();
    var nest_asset = player.getNestAsset();        
    var nest_ancestor = this.game.getAsset( player.getNestAnscestorId() );

    var foundObjects = [];
		for(var i = 0; i < list.length; i++) 
    {
      var object, object_parent, object_ancestor, object_ancestor;
      
      object = this.game.getAsset( list[i] );

      if(!object) continue;

      if( object instanceof adventurejs.Substance )
      {
        // automatically return substances as present
        foundObjects.push( list[i] );
        continue;
      }


      // abstractions are always reachable
      if( object.is.abstract ) 
      { 
        foundObjects.push( list[i] );
        continue;
      }  

      // if object is a plug, test against its parent
      if( object.IOVisConnectedToAnything('plug') )
      {
        object = object.getPlaceAsset();
      }

      object_parent = object.getPlaceAsset();
      object_ancestor = this.game.getAsset( object.getAncestorId() );

      // player is carrying it, ok
      //if( object.isIn( player ) ) { 
      if( object.isIn( player ) ) 
      { 
        foundObjects.push( list[i] );
        continue;
      }  

      // player is in it, ok
      if( player.isNested() 
      && object.id === nest_asset.id ) 
      {
        foundObjects.push( list[i] );
        continue;
      }  

      // if player is nested and trying to get up/down
      if( player.isNested() 
      && object.direction === "down"
      || object.direction === "up" ) 
      {
        foundObjects.push( list[i] );
        continue;
      }  
  
      // if player is in/on/under/behind something
      if( player.isNested() 

        // player is not nested in object
        && object.id !== nest_asset.id

        // it's not top of the nest
        && object.id !== nest_ancestor.id

        // it's not in inventory
        //&& object_ancestor.id !== player.id 

        // it's not nested in same container as player
        && object_parent.id !== nest_asset.id

        // it's not nested in same container as player
        && object_ancestor.id !== nest_ancestor.id

        // it's not explicitly reachable from thing player is nested in
        && !nest_asset.canPlayerReachThatFromThis( object )

        // it's not inside another thing that is 
        // explicitly reachable from thing player is nested in
        && !nest_asset.canPlayerReachThatFromThis( object_ancestor )

      ){
        console.warn( "reachable excluded", object.id );
        continue;
      }

      // is player on the floor, but object not on the floor?
      // this check might be too restrictive
      if( !player.isNested()
      && player.isOnFloor()
      && !(object instanceof adventurejs.Floor)
      && object.getPlaceAssetId() !== player.getPlaceAssetId() ) 
      {
        console.warn( "Exclude " + object.name + " because player is on the floor." );
        continue;
      }

      // is player at different y height?
      // figure out y overlap
      var range = object.getYRange();
      // is player close enough on y?
      if( player.position.y < range.min || player.position.y > range.max ) 
      {
        console.warn( "Exclude " + object.name + " because player at different y." );
        continue;
      }

			/*
				TODO
				on top of a tall object?
        behind glass?
        inside something that's closed?
			*/

			foundObjects.push( list[i] );
		}

    //console.warn( "selectReachable returned " + foundObjects );
		return foundObjects;
	}
  
}());