/// <summary> /// Creates and starts the test duel. /// </summary> public void Start() { // Open the settings file. var settings = JObject.Parse(File.ReadAllText("game.json")); // Create the random object. If the settings file has a provided seed we use it. ManagedRandom rand; if (settings["RandomSeed"].Type == JTokenType.Null) { rand = new ManagedRandom(); } else { rand = new ManagedRandom(settings["RandomSeed"].ToObject <int>()); } EnvironmentContainer env = new EnvironmentContainer() { AnimationBlocker = new PlaybackBlockingHandler(), Content = new LoadedContent(), Lua = new LuaEnvironment(), Random = rand, Settings = new DuelSettings() }; // Provide the content loader with directory information. ContentLoader.SetContentDirectory(settings["ContentDirectory"].ToString()); // Register loading to the current environemt. ContentLoader.RegisterLoads(env.Content, env.Lua); // Tell the loader to log anything that is loaded. ContentLoader.LogLoads = true; // Get the commands stored in the json file as we will have to load them. var commands = (settings["LoadCommands"] as JArray).Values <string>(); // Apart from commands we also have to manually load the lua functions we provide to the DuelFlow. var cmds = new List <string>(commands) { settings["GameStart"].ToString(), settings["ChangeTurn"].ToString(), settings["GameEnd"].ToString(), }; // Load all the system and command actions. foreach (var cmd in cmds) { ContentLoader.LoadAction(cmd, env.Content, env.Lua); } // Tell the duel flow what we want it to do for the varaible actions. env.Settings.GameStartAction = env.Content.GetAction(settings["GameStart"].ToString()); env.Settings.ChangeTurnAction = env.Content.GetAction(settings["ChangeTurn"].ToString()); env.Settings.GameEndAction = env.Content.GetAction(settings["GameEnd"].ToString()); // Disable animations as we won't see anything on console application and it will just cause slow down. env.Settings.AnimationSpeed = DuelSettings.NO_ANIM; // Create the players. var Player1 = ConstructPlayer(settings["Player1"], env); var Player2 = ConstructPlayer(settings["Player2"], env); // Write a summary of every thing we have loaded. Console.WriteLine("------------------------------"); foreach (string s in env.Content.GetAllKeysSummary()) { Console.WriteLine(s); } // Determine who goes fist. Set as player1 to initalise and causes less lines of code. Player goesFist = Player1; switch (settings["GoesFirst"].ToString()) { case "Player2": goesFist = Player2; break; case "Random": // If the first player is random we need to use the ManagedRandom to decide. int val = env.Random.Next(0, 2); if (val == 0) { goesFist = Player2; } break; } // Create and ready the duel flow. DuelFlow flow = new DuelFlow(env, Player1, Player2, goesFist); // Add all the cards the players asked for to their hands. AddCardsToPlayer(flow, Player1, settings["Player1"], env); AddCardsToPlayer(flow, Player2, settings["Player2"], env); // Provide the callback functions with a simple console print statement. flow.OutBoundDelegate += (object sender, ClientRequest data) => { Console.WriteLine(data.RequestId + " sent to all players."); }; Player1.OutBoundDelegate += (object sender, ClientRequest data) => { Console.WriteLine(data.RequestId + " sent to " + Player1.UserId); }; Player2.OutBoundDelegate += (object sender, ClientRequest data) => { Console.WriteLine(data.RequestId + " sent to " + Player2.UserId); }; // Stop any loading from happening during gameplay as it will cause slowdown. ContentLoader.DeregisterLoads(env.Lua); // Start the duel. Thread loop = flow.Start(); while (flow.State.OnGoing) { //Delay the thread incase of ongoing logic. Thread.Sleep(50); // Get the player whose turn it currently is. var towner = flow.State.CurrentTurn.Owner; // Display information about the game. Console.WriteLine(); // Whose turn it is. Display.Turn(flow.State.CurrentTurn); // TurnOwner's stats. Display.PlayerStats(towner); // Other Player's stats. Display.PlayerStats(flow.State.GetOpposingPlayer(towner)); Console.WriteLine(); // And the field. Display.Field(flow.State.Field); Console.WriteLine(); Console.WriteLine(); // Get input from the console. string x = Console.ReadLine(); // Clear the consloe for the next command. Console.Clear(); // Split the command into its components. string[] splits = x.Split(' '); switch (splits[0].ToLower()) { case "level": flow.EnqueueCommand("CMDLevelUp", towner); break; case "levelup": flow.EnqueueCommand("CMDLevelUp", towner); break; case "disc": if (splits.Length != 2) { Console.WriteLine("Please provide a card number. example: disc 2"); break; } if (towner.Hand.Count == 0) { Console.WriteLine("Your hand is empty."); break; } if (int.TryParse(splits[1], out int index)) { if (index > towner.Hand.Count - 1) { Console.WriteLine("Card number provided is to high."); break; } if (index < 0) { Console.WriteLine("Card number cannot be negative"); break; } flow.EnqueueCommand("CMDDiscard", towner, towner.Hand.ElementAt(index)); break; } else { Console.WriteLine("Please provide a card number. example: disc 2"); break; } case "discard": if (splits.Length != 2) { Console.WriteLine("Please provide a card number. example: discard 2"); break; } if (towner.Hand.Count == 0) { Console.WriteLine("Your hand is empty."); break; } if (int.TryParse(splits[1], out int index2)) { if (index2 > towner.Hand.Count - 1) { Console.WriteLine("Card number provided is to high."); break; } if (index2 < 0) { Console.WriteLine("Card number cannot be negative"); break; } flow.EnqueueCommand("CMDDiscard", towner, towner.Hand.ElementAt(index2)); break; } else { Console.WriteLine("Please provide a card number. example: discard 2"); break; } case "hand": Display.Collection("Hand", towner.Hand); break; case "grave": Display.Collection("Grave", towner.Grave); break; case "revive": flow.EnqueueCommand("CMDRevive", towner); break; case "rev": flow.EnqueueCommand("CMDRevive", towner); break; case "play": if (splits.Length != 3) { Console.WriteLine("Please provide a card number and a position. example: play 2 4"); Console.WriteLine("This would place card 2 in position 4."); break; } if (towner.Hand.Count == 0) { Console.WriteLine("Your hand is empty."); break; } if (int.TryParse(splits[1], out int index3)) { if (index3 > towner.Hand.Count - 1) { Console.WriteLine("Card number provided is to high."); break; } if (index3 < 0) { Console.WriteLine("Card number cannot be negative"); break; } if (int.TryParse(splits[2], out int pos)) { if (pos > flow.State.Field.Count() - 1 || pos < 0) { Console.WriteLine("Position must be a spot on the field. MaxPos: " + flow.State.Field.Count()); break; } flow.EnqueueCommand("CMDPlayCard", towner, towner.Hand.ElementAt(index3), flow.State.Field[pos]); break; } else { Console.WriteLine("Please provide a card number and a position. example: play 2 4"); Console.WriteLine("This would place card 2 in position 4."); break; } } else { Console.WriteLine("Please provide a card number and a position. example: play 2 4"); Console.WriteLine("This would place card 2 in position 4."); break; } case "charge": flow.EnqueueCommand("CMDCharge", towner); break; case "end": loop.Abort(); break; case "help": Console.WriteLine("Commands: [charge, play, level(up), disc(ard), rev(ive), hand, grave, help]"); break; default: Console.WriteLine(x + " is not a valid command."); Console.WriteLine("Commands: [charge, play, level(up), disc(ard), rev(ive), hand, grave, help]"); break; } } Console.WriteLine("Game Over - Press Any Key to Terminate"); Console.ReadLine(); }