How to setup a sandobox? [closed]

Hey coders!

I’m trying to prepare for the next challenge and i saw a lot of top coders used to code sandbox to simulate the game outside of the CG platform. This is really a good point and i would like to do the same.

BUT, i can’t figure out how to perform the communication between the two program (sandbox and IA).

I working on linux so i first think about some exotic bash circular pipe but i’m no even sure this is possible.

How would/did you set up a sandbox?

Thank for help.

Yorwan

EDIT: Just in case this would be straightforward in a given programming language i mainly use C/C++

There are many ways this could be accomplished, depending on your goals, language selection, and development environment. If you’re familiar with software testing practices, I’d recommend using such techniques. I tend to use C# for most of my current development, so I’ll use that as an example.

I do my development in Visual Studio and use the MSTest framework to create unit tests for my AI. CG begins execution in static void Main() and reads input from stdin. I leave the game initialization input parsing in Main(), but then immediately jump out of static context by creating an instance of my AI class. For example, my Main() for Hypersonic looks like:

namespace HyperSonic {
    public class Player {
        public static int Width;
        public static int Height;
        public static int MyId;

        public static void Main(string[] args) {
            var inputs = Console.ReadLine().Split(' ');
            Width = int.Parse(inputs[0]);
            Height = int.Parse(inputs[1]);
            MyId = int.Parse(inputs[2]);
            var p = new Player();

            while (true) {
                var move = p.PlayOneRound();
                Console.WriteLine(move);
            }
        }
    }
}

Then, there’s per-round input parsing. This I accomplish via protected methods that can be overridden, using the unit testing concept of object seams. For example:

    public string PlayOneRound() {
        SetupGrid();
        SetupEntities();

        // logic goes here!

        return reallyAwesomeMove;
    }

    private void SetupGrid() {
        _startState = new State();
        _startState.Grid = Enumerable.Range(0, Height)
            .Select(_ => GetNextBoardLine().ToCharArray())
            .ToArray();
    }

    protected virtual string GetNextBoardLine() {
        return Console.ReadLine();
    }

    private void SetupEntities() {
        var numEntities = GetNumEntities();
        for (var i = 0; i < numEntities; i++) {
            var inputs = GetNextEntity().Split(' ');
            var entityType = int.Parse(inputs[0]);
            var owner = int.Parse(inputs[1]);
            var x = int.Parse(inputs[2]);
            var y = int.Parse(inputs[3]);
            var param1 = int.Parse(inputs[4]);
            var param2 = int.Parse(inputs[5]);
        }
    }

    protected virtual int GetNumEntities() {
        return int.Parse(Console.ReadLine());
    }

    protected virtual string GetNextEntity() {
        return Console.ReadLine();
    }

From here, it’s very easy to create a test class that overrides these inputs:

namespace HyperSonic {

    [TestClass]
    public class PlayerTest {

        [TestMethod]
        public void ShouldComeUpWithReallyAwesomeMove() {
            var p = new PlayerForTest(4, 4);
            p.SetupForRound(new[] {
                "....",
                "....",
                "....",
                "...0"
            }, new[] {
                "0 0 0 0 1 3"
            });

            var move = p.PlayOneRound();
            Assert.IsReallyAwesome(move);
        }

        private class PlayerForTest : Player {
            private List<string> _gridLines;
            private List<string> _entities;

            public PlayerForTest(int width, int height) {
                Width = width;
                Height = height;
                MyId = 0;
            }

            internal void SetupForRound(string[] grid, string[] entities) {
                _gridLines = grid.ToList();
                _entities = entities.ToList();
            }

            protected override int GetNumEntities() {
                return _entities.Count;
            }

            protected override string GetNextEntity() {
                var entity = _entities[0];
                _entities.RemoveAt(0);
                return entity;
            }

            protected override string GetNextBoardLine() {
                var line = _gridLines[0];
                _gridLines.RemoveAt(0);
                return line;
            }
        }
    }
}

Hopefully, it should be pretty obvious how you could use this formula to expand from single-move testing to a framework that can pit two different AIs (separate class instances) against each other.

Make sense?

  • danBhentschel
1 Like

:sweat_smile: (painful smile)

Thank you for this well documented answerd that i will analyse in deep. I’m afraid i’m not well used to software testing so this seems a bit hard for me.I will consider this possibility whatever but i used to think there should be a more easy way to do this.

I suppose it’s coded using files or stream in the CG environement and that’s more what i’m looking for.

Ok problem solved i have found what i wanted using named pipes in bash.

For those interested:

$ mkfifo fifo1 fifo2
$ ./sandbox > fifo1 < fifo2 &
$ ./ia > fifo2 < fifo1 &

I suppose getting a IA implementation self contained in a class as proposed by player_one is the proper way to go for more advanced features but this one is enough for me :wink:

EDIT: After some googling i find exactly what i wanted, which is the piping of forked program. In C this involve stuff as fork(),exec commands,pipe(),dup2(). If someone is interested to discuss of it it’s cool otherwise subject is closed.

1 Like