public void do_fov_rec_shadowcast(int x, int y, int radius)
    {
        FOV_set_this_run.Fill(false);
        in_FOV.Fill(false);

        Action <int, int> ff = (int xx, int yy) =>
        {
            in_FOV.AtSet(xx, yy, true);
            fogofwar.AtSet(xx, yy, false);
            Etilesprite et = displaychar.AtGet(xx, yy);
            //new debug
            if ((int)et < 0 || (int)et > 255)
            {
                Debug.Log("ET OUT OF BOUNDS =" + (int)et);
            }
            //end new debug
            playermemory.AtSet(xx, yy, et);

            if (itemgrid[xx, yy] != null && itemgrid[xx, yy].ismob == false)
            {
                minimap.SetPixel(xx, yy, (Color)minimapcolours[(int)itemgrid[xx, yy].tile]);
            }
            else
            {
                if (buildings[xx, yy] != Etilesprite.EMPTY)
                {
                    minimap.SetPixel(xx, yy, (Color)minimapcolours[(int)buildings[xx, yy]]);
                }
                else
                {
                    minimap.SetPixel(xx, yy, (Color)minimapcolours[(int)et]);
                }
            }
            //if (et == Etilesprite.WALL) minimap.SetPixel(xx, yy, Color.grey);
            //else if (et == Etilesprite.FLOOR) minimap.SetPixel(xx, yy, Color.black);
        };

        for (sbyte i = 0; i < 8; i++)
        {
            cast_light(x, y, radius, 1, 1.0f, 0.0f, multipliers[0, i],
                       multipliers[1, i], multipliers[2, i], multipliers[3, i],
                       ff
                       );
        }
        ff(x, y);

        minimap.SetPixel(this.player.posx, this.player.posy, Color.magenta);
        minimap.Apply(false);
    }
    public void do_fov_foradynamiclight(int callx, int cally, int radius, Color clr)
    {
        FOV_set_this_run.Fill(false);

        //

        Action <int, int> ff = (int xx, int yy) =>
        {
            dolight(callx, cally, xx, yy, radius, clr, false);//dynamiclight.AtGet(xx, yy)); new 18 jan
        };

        for (int i = 0; i < 8; i++)
        {
            cast_light(callx, cally, radius, 1, 1.0f, 0.0f, multipliers[0, i],
                       multipliers[1, i], multipliers[2, i], multipliers[3, i],
                       ff
                       );
        }
        ff(callx, cally);
    }
    //static Color walllight = new Color(1.0f, 0.30859375f, 0.5f);

    //FOV STUFF
    //from http://www.roguebasin.com/index.php?title=C%2B%2B_shadowcasting_implementation
    // "A C++ implementation of Bjorn Bergstrom's recursive shadowcasting FOV algorithm."

    void cast_light(int x, int y, int radius, int row,
                    float start_slope, float end_slope, int xx, int xy, int yx,
                    int yy, Action <int, int> WhatToDo)
    {
        if (start_slope < end_slope)
        {
            return;
        }
        float next_start_slope = start_slope;

        for (int i = row; i <= radius; i++)
        {
            bool blocked = false;
            for (int dx = 0 - i, dy = 0 - i; dx <= 0; dx++)
            {
                float l_slope = (dx - 0.5f) / (dy + 0.5f);
                float r_slope = (dx + 0.5f) / (dy - 0.5f);
                if (start_slope < r_slope)
                {
                    continue;
                }
                else if (end_slope > l_slope)
                {
                    break;
                }

                int sax = dx * xx + dy * xy;
                int say = dx * yx + dy * yy;
                if ((sax < 0 && (int)Math.Abs(sax) > x) ||
                    (say < 0 && (uint)Math.Abs(say) > y))
                {
                    continue;
                }
                int ax = x + sax;
                int ay = y + say;
                if (ax >= width || ay >= height)
                {
                    continue;
                }

                int radius2 = radius * radius;
                if ((uint)(dx * dx + dy * dy) < radius2)
                {
                    if (!FOV_set_this_run.AtGet(ax, ay))
                    {
                        FOV_set_this_run.AtSet(ax, ay, true);
                        WhatToDo(ax, ay);
                    }
                }

                if (blocked)
                {
                    if (blocks_sight.AtGet(ax, ay))
                    {
                        next_start_slope = r_slope;
                        continue;
                    }
                    else
                    {
                        blocked     = false;
                        start_slope = next_start_slope;
                    }
                }
                else if (blocks_sight.AtGet(ax, ay))
                {
                    blocked          = true;
                    next_start_slope = r_slope;
                    cast_light(x, y, radius, i + 1, start_slope, l_slope, xx,
                               xy, yx, yy, WhatToDo);
                }
            }
            if (blocked)
            {
                break;
            }
        }
    }
    void do_fov_foralight(int callx, int cally, int radius, Color clr, sbyte directional = -1)
    {
        //if (directional != 1) return;
        FOV_set_this_run.Fill(false);

        //auto ff = [this, callx, cally, radius, clr,directional](uint xx, uint yy){
        Action <int, int> ff = (int xx, int yy) =>
        {
            if (directional == -1)
            {
                goto lightit;
            }
            if (callx == xx && cally == yy)
            {
                goto lightit;
            }
            switch (directional)
            {
            case 0:    //n
                if (yy >= cally)
                {
                    return;
                }
                break;

            case 1:    //s
                if (yy <= cally)
                {
                    return;
                }
                break;

            case 2:    //e
                if (xx <= callx)
                {
                    return;
                }
                break;

            case 3:    //w
                if (xx >= callx)
                {
                    return;
                }
                break;
            }
lightit:
            dolight(callx, cally, xx, yy, radius, clr, true);//staticlight.AtGet(xx, yy)); new 18 jan
        };



        for (uint i = 0; i < 8; i++)
        {
            cast_light(callx, cally, radius, 1, 1.0f, 0.0f, multipliers[0, i],
                       multipliers[1, i], multipliers[2, i], multipliers[3, i],
                       ff//crash
                       );
        }
        ff(callx, cally);
    }