public int GetActionCost(Character.direction dir)
    {
        if (dir == (Character.direction)(-1))
        {
            return(0);
        }
        if (world[agentPos[0], agentPos[1]].item == Item.ItemType.NONE)
        {
            //Debug.Log("cat");
        }
        else
        {
            //Debug.Log("cate");
        }
        // subtract 1 from number of item tiles for this calculation if we're on an item tile
        int dirtyTiles = GetItemTiles().Count - (world[agentPos[0], agentPos[1]].item != Item.ItemType.NONE ? 1 : 0);

        //int turnAround = cameFrom == null ? 0 : (Character.OppositeDirection(dir, cameFrom.actionPerformed) ? 1 : 0) * 5;
        return(1 + 2 * dirtyTiles + (int)Pacman.GetDistPenalty(agentPos));       // + turnAround;
    }
    // TODO: account for impassable tiles
    public Node affect(Character.direction dir)
    {
        TileData[,] newWorld = new TileData[MapGene.mapHeight, MapGene.mapWidth];
        for (int i = 0; i < MapGene.mapHeight; i++)
        {
            for (int j = 0; j < MapGene.mapWidth; j++)
            {
                // erase the dot we just succed
                if (i == agentPos.x && j == agentPos.y)
                {
                    newWorld[i, j] = goal.world[i, j];
                }
                else
                {
                    newWorld[i, j] = world[i, j];
                }
                //newWorld[i, j] = world[i, j].Copy();
            }
        }
        // erase the dot we just succed
        //newWorld[agentPos[0], agentPos[1]].item = Item.ItemType.NONE;
        Vector2Int newAgentPos = Vector2Int.zero;

        switch (dir)
        {
        case Character.direction.RIGHT:
            newAgentPos = new Vector2Int(agentPos.x, (agentPos.y + 1) % MapGene.mapWidth);
            break;

        case Character.direction.UP:
            int newx = agentPos.x - 1;
            newAgentPos = new Vector2Int(newx < 0 ? MapGene.mapHeight + newx : newx, agentPos.y);
            break;

        case Character.direction.LEFT:
            int newy = agentPos.y - 1;
            newAgentPos = new Vector2Int(agentPos.x, newy < 0 ? MapGene.mapWidth + newy : newy);
            break;

        case Character.direction.DOWN:
            newAgentPos = new Vector2Int((agentPos.x + 1) % MapGene.mapHeight, agentPos.y);
            break;
        }
        if (!world[newAgentPos.x, newAgentPos.y].passable || Character.TheresAGhostHere(newAgentPos) && Character.charState != Character.state.REVERSE)
        {
            return(null);               // invalid action (hitting a wall)
        }
        Node n = new Node(newWorld, newAgentPos, dir);

        n.cameFrom = this;
        n.goal     = goal;
        //n.itemTiles = new List<TileData>(itemTiles.ToArray());
        n.itemTiles = new List <TileData>();
        for (int i = 0; i < itemTiles.Count; i++)
        {
            // copy itemTile data over, but use the tile objects from newWorld
            n.itemTiles.Add(newWorld[itemTiles[i].ij.x, itemTiles[i].ij.y]);
        }
        // remove the item at the position that the agent was
        n.itemTiles.Remove(newWorld[agentPos.x, agentPos.y]);
        return(n);
    }
 public Node(TileData[,] world, Vector2Int agentPos, Character.direction action)
 {
     this.world      = world;
     this.agentPos   = agentPos;
     actionPerformed = action;
 }