示例#1
0
        public ActionResult AI_vs_AI(string id, int?version, int[] difficulty)
        {
            VariantService variants      = GetService <VariantService>();
            VariantVersion versionToPlay = DeterminePlayVersion(id, version, variants);

            if (versionToPlay == null)
            {
                return(HttpNotFound("Cannot determine variant version to play"));
            }

            var model = new GamePlayModel(versionToPlay, GameMode.AI_vs_AI);
            var AIs   = variants.ListAiDifficulties();

            model.Players = new PlayerModel[versionToPlay.Variant.PlayerCount];
            for (var i = 0; i < model.Players.Length && i < difficulty.Length; i++)
            {
                model.Players[i] = AIs.Single(ai => ai.ID == difficulty[i]);
            }

            for (var i = difficulty.Length; i < model.Players.Length; i++)
            {
                model.Players[i] = model.Players[difficulty.Length];
            }

            return(View("Play", model));
        }
示例#2
0
        private VariantVersion DeterminePlayVersion(string variantTag, int?versionID, VariantService variants)
        {
            var variant = variants.GetByTag(variantTag);

            if (variant == null)
            {
                return(null);
            }

            if (versionID.HasValue && variant.CreatedBy.Name == User.Identity.Name)
            {
                VariantVersion version = variants.GetVersionNumber(variant, versionID.Value);

                if (version == null || version.VariantID != variant.ID)
                {
                    return(null);
                }

                return(version);
            }
            else
            {
                return(variant.PublicVersion);
            }
        }
示例#3
0
 public bool CanDelete(VariantVersion version)
 {
     // versions can be deleted only if they are associated with no games at all, active or otherwise.
     // public versions can not be deleted.
     return(!version.Games.Any() &&
            (!version.Variant.PublicVersionID.HasValue || version.Variant.PublicVersionID != version.ID) &&
            version.Variant.AllVersions.Count > 1);
 }
示例#4
0
        public void SaveLinkData(VariantVersion version, string linkData)
        {
            var definition = GetDefinition(version);
            var board      = definition.Board;

            SaveLinkData(definition, board, linkData);
            definition.Board     = board;
            version.LastModified = DateTime.Now;
            Entities.SaveChanges();
        }
示例#5
0
        public ActionResult Definition(string id, int?version)
        {
            VariantService variants      = GetService <VariantService>();
            VariantVersion versionToPlay = DeterminePlayVersion(id, version, variants);

            if (versionToPlay == null)
            {
                return(HttpNotFound("Cannot determine variant version to play"));
            }

            return(Content(versionToPlay.Definition, "text/xml"));
        }
示例#6
0
        public XmlDocument GetBoardSVG(VariantVersion version, bool addArrowheadDef = false, bool showCellRefs = false)
        {
            var board = GetDefinition(version).Board;

            XmlDocument svgDoc = new XmlDocument();

            svgDoc.AppendChild(svgDoc.CreateElement("svg"));

            if (addArrowheadDef)
            {
                // add a <defs> section containing an arrowhead marker
                var defs = svgDoc.CreateElement("defs");
                defs.InnerXml = @"<marker id=""arrowhead"" viewbox=""0 0 10 10"" refX=""1"" refY=""5"" markerWidth=""6"" markerHeight=""6"" orient=""auto""><path d=""M 0 0 L 10 5 L 0 10 z"" /></marker>";
                svgDoc.DocumentElement.AppendChild(defs);
            }

            var attr = svgDoc.CreateAttribute("xmlns");

            attr.Value = "http://www.w3.org/2000/svg";
            svgDoc.DocumentElement.Attributes.Append(attr);

            attr       = svgDoc.CreateAttribute("id");
            attr.Value = "render";
            svgDoc.DocumentElement.Attributes.Append(attr);

            attr       = svgDoc.CreateAttribute("viewBox");
            attr.Value = board.Attributes["viewBox"].Value;
            svgDoc.DocumentElement.Attributes.Append(attr);

            foreach (XmlNode node in board.ChildNodes)
            {
                if (node.Name == "cell")
                {
                    WriteCellToSVG(node, svgDoc);
                }
                else if (node.Name == "line")
                {
                    WriteLineToSVG(node, svgDoc);
                }
            }

            if (showCellRefs) // done last, so that references appear on top of lines
            {
                foreach (XmlNode node in board.SelectNodes("cell"))
                {
                    WriteCellRefToSVG(node, svgDoc);
                }
            }

            return(svgDoc);
        }
示例#7
0
        public VariantVersion CreateNewVersion(VariantVersion version)
        {
            var newestVersion = version.Variant.AllVersions.OrderByDescending(v => v.Number).FirstOrDefault();
            int versionNum    = newestVersion == null ? 1 : newestVersion.Number + 1;

            var newVersion = Entities.Entry(version).GetDatabaseValues().ToObject() as VariantVersion;

            newVersion.LastModified = DateTime.Now;
            newVersion.Number       = (short)versionNum;
            Entities.VariantVersions.Add(newVersion);
            Entities.SaveChanges();

            return(newVersion);
        }
示例#8
0
        public string GetCellLinks(VariantVersion version)
        {
            var board = GetDefinition(version).Board;
            var sb    = new StringBuilder();

            foreach (XmlNode cell in board.SelectNodes("cell"))
            {
                foreach (XmlNode link in cell.SelectNodes("link"))
                {
                    sb.AppendFormat(";{0}:{1}:{2}", cell.Attributes["id"].Value, link.Attributes["dir"].Value, link.Attributes["to"].Value);
                }
            }

            return(sb.ToString());
        }
示例#9
0
        public void SaveCellReferenceChanges(VariantVersion version, string renameData)
        {
            var definition = GetDefinition(version);
            var board      = definition.Board;

            var renames = renameData.Split(outerSep, StringSplitOptions.RemoveEmptyEntries);

            foreach (var rename in renames)
            {
                var parts = rename.Split(innerSep);
                if (parts.Length != 2)
                {
                    continue;
                }

                var from = parts[0];
                var to   = parts[1];

                var alreadyExists = board.SelectSingleNode(string.Format("cell[@id='{0}']", to));
                if (alreadyExists != null)
                {
                    continue;
                }

                // find the "from" cell, and change its ID to the "to" value.
                var cell = board.SelectSingleNode(string.Format("cell[@id='{0}']", from));
                if (cell == null)
                {
                    continue;
                }
                cell.Attributes["id"].Value = to;

                // do the same for ALL links to this cell
                var links = board.SelectNodes(string.Format("cell/link[@to='{0}']", from));
                foreach (XmlNode link in links)
                {
                    link.Attributes["to"].Value = to;
                }
            }

            definition.Board     = board;
            version.LastModified = DateTime.Now;
            Entities.SaveChanges();
        }
示例#10
0
        public IEnumerable <string> ListGlobalDirections(VariantVersion version)
        {
            SortedSet <string> directions = new SortedSet <string>();

            var board = GetDefinition(version).Board;

            foreach (XmlNode fromCell in board.SelectNodes("cell"))
            {
                foreach (XmlNode link in fromCell.ChildNodes)
                {
                    var dir = link.Attributes["dir"].Value;
                    if (!directions.Contains(dir))
                    {
                        directions.Add(dir);
                    }
                }
            }

            return(directions);
        }
示例#11
0
        public string GetDirectionGroups(VariantVersion version)
        {
            var definition = GetDefinition(version);
            var groups     = definition.Dirs.SelectNodes("group");

            var sb = new StringBuilder();

            foreach (XmlNode groupNode in groups)
            {
                sb.Append(outerSep);
                sb.Append(groupNode.Attributes["name"].Value);

                foreach (XmlNode dir in groupNode.ChildNodes)
                {
                    sb.Append(innerSep);
                    sb.Append(dir.Attributes["dir"].Value);
                }
            }
            return(sb.ToString());
        }
示例#12
0
        public void SaveDirectionGroups(VariantVersion version, string groupData)
        {
            var definition = GetDefinition(version);
            var root       = definition.Dirs;

            if (root == null)
            {
                root = definition.Dirs = definition.CreateElement("dirs");
            }
            else
            {
                // clear existing direction groups
                var existingGroups = root.SelectNodes("group");
                foreach (XmlNode group in existingGroups)
                {
                    group.ParentNode.RemoveChild(group);
                }
            }

            var groups = groupData.Split(outerSep, StringSplitOptions.RemoveEmptyEntries);

            foreach (string group in groups)
            {
                var groupParts = group.Split(innerSep);

                var groupNode = definition.CreateElement("group");
                groupNode.Attributes.Append(definition.CreateAttribute("name", groupParts[0]));

                for (int i = 1; i < groupParts.Length; i++)
                {
                    var linkNode = definition.CreateElement("include");
                    linkNode.Attributes.Append(definition.CreateAttribute("dir", groupParts[i]));
                    groupNode.AppendChild(linkNode);
                }
                root.AppendChild(groupNode);
            }
            definition.Dirs      = root;
            version.LastModified = DateTime.Now;
            Entities.SaveChanges();
        }
示例#13
0
        public bool SaveBoardData(VariantVersion version, string boardSVG, string cellLinks)
        {
            XmlDocument svgDoc = new XmlDocument();

            try
            {
                svgDoc.LoadXml(boardSVG);
            }
            catch
            {
                return(false);
            }

            var definition = GetDefinition(version);
            var board      = definition.CreateElement("board");

            var viewBox = definition.CreateAttribute("viewBox");

            viewBox.Value = svgDoc.DocumentElement.HasAttribute("viewBox") ? svgDoc.DocumentElement.Attributes["viewBox"].Value : definition.Board.Attributes["viewBox"].Value;
            board.Attributes.Append(viewBox);

            foreach (XmlNode node in svgDoc.DocumentElement.ChildNodes)
            {
                if (node.Name == "path")
                {
                    SaveCellFromSVG(node, board);
                }
                else if (node.Name == "line")
                {
                    SaveLineFromSVG(node, board);
                }
            }

            SaveLinkData(definition, board, cellLinks);
            definition.Board     = board;
            version.LastModified = DateTime.Now;
            Entities.SaveChanges();
            return(true);
        }
示例#14
0
        public string GetRelativeDirs(VariantVersion version)
        {
            StringBuilder sb      = new StringBuilder();
            var           dirRoot = GetDefinition(version).Dirs;

            if (dirRoot == null)
            {
                return(string.Empty);
            }

            foreach (XmlNode relativeNode in dirRoot.SelectNodes("relative"))
            {
                var relDir = relativeNode.Attributes["name"].Value;

                foreach (XmlNode link in relativeNode.ChildNodes)
                {
                    sb.AppendFormat(";{0}:{1}:{2}", link.Attributes["from"].Value, relDir, link.Attributes["to"].Value);
                }
            }

            return(sb.ToString());
        }
示例#15
0
        public IEnumerable <string> ListRelativeDirections(VariantVersion version)
        {
            SortedSet <string> directions = new SortedSet <string>();

            var dirRoot = GetDefinition(version).Dirs;

            if (dirRoot == null)
            {
                return(new string[0]);
            }

            foreach (XmlNode relativeNode in dirRoot.SelectNodes("relative"))
            {
                var dir = relativeNode.Attributes["name"].Value;
                if (!directions.Contains(dir))
                {
                    directions.Add(dir);
                }
            }

            return(directions);
        }
示例#16
0
        public ActionResult New([Bind(Include = "Name,NumPlayers,Description,HelpText")] VariantEditModel model)
        {
            if (!ModelState.IsValid)
            {
                return(RedirectToAction("New"));
            }

            UserService    users    = GetService <UserService>();
            VariantService variants = GetService <VariantService>();

            var user = users.GetByName(User.Identity.Name);

            var variant = new Variant();

            variant.CreatedByID = user.ID;
            variant.Description = model.Description ?? string.Empty;
            variant.HelpText    = DataService.StripTags(model.HelpText ?? string.Empty);
            variant.PlayerCount = (byte)model.NumPlayers;

            if (!ValidateName(model, variant))
            {
                return(View(model));
            }

            var version = new VariantVersion();

            version.Number       = 1;
            version.LastModified = DateTime.Now;
            version.Variant      = variant;
            version.Definition   = string.Empty;

            Entities().Variants.Add(variant);
            Entities().VariantVersions.Add(version);
            Entities().SaveChanges();

            return(RedirectToAction("Shape", "Designer", new { version.ID }));
        }
示例#17
0
        public ActionResult Offline(string id, int?version)
        {
            VariantService variants      = GetService <VariantService>();
            VariantVersion versionToPlay = DeterminePlayVersion(id, version, variants);

            if (versionToPlay == null)
            {
                return(HttpNotFound("Cannot determine variant version to play"));
            }

            var model = new GamePlayModel(versionToPlay, GameMode.Offline);

            model.Players = new PlayerModel[versionToPlay.Variant.PlayerCount];
            for (int i = 0; i < model.Players.Length; i++)
            {
                model.Players[i] = new PlayerModel()
                {
                    IsLocal = true
                }
            }
            ;

            return(View("Play", model));
        }
示例#18
0
 public VariantDefinition GetDefinition(VariantVersion version)
 {
     // at some point this should be made to cache definitions, but we have to make sure it updates the cache when they're modified
     return(new VariantDefinition(version));
 }
示例#19
0
 public static string DescribeVersion(VariantVersion version)
 {
     return(string.Format("v{0} @ {1}", version.Number, version.LastModified.ToString("d")));
 }
示例#20
0
 public bool IsAllowedToPlay(VariantVersion version, string userName)
 {
     return((version.Variant.PublicVersionID.HasValue && version.Variant.PublicVersionID == version.ID) || version.Variant.CreatedBy.Name == userName);
 }
示例#21
0
        private bool ValidateNewGame(GameMode modeSelect, int?variantSelect, int?aiSelect, string[] opponent, VariantService variants, out VariantVersion version, out List <User> opponentUsers, out AIDifficultyModel aiDifficulty)
        {
            opponentUsers = null;
            aiDifficulty  = default(AIDifficultyModel);

            // is variant version ID valid?
            version = variantSelect.HasValue ? Entities().VariantVersions.Find(variantSelect.Value) : null;
            if (version == null)
            {
                ModelState.AddModelError("variantSelect", "Please select a variant.");
                return(false);
            }

            // can user access variant version?
            UserService users = GetService <UserService>();

            if (!users.IsAllowedToPlay(version, User.Identity.Name))
            {
                ModelState.AddModelError("variantSelect", "Cannot access selected variant version.");
                return(false);
            }

            // if game mode is public, is variant version public?
            if (modeSelect == GameMode.Public && (!version.Variant.PublicVersionID.HasValue || version.Variant.PublicVersionID != version.Variant.PublicVersionID))
            {
                ModelState.AddModelError("variantSelect", "Public games cannot use a private variant.");
                return(false);
            }

            // if game mode is AI, is difficulty selection valid?
            aiDifficulty = aiSelect.HasValue ? variants.ListAiDifficulties().SingleOrDefault(ai => ai.ID == aiSelect.Value) : null;
            if (modeSelect == GameMode.AI && aiDifficulty == null)
            {
                ModelState.AddModelError("aiSelect", "Invalid AI difficulty.");
                return(false);
            }

            // if game mode is private, are all opponent fields filled in, valid users, not the current user, and not duplicated?
            if (modeSelect == GameMode.Private)
            {
                if (opponent.Length != version.Variant.PlayerCount - 1 || opponent.Count(o => string.IsNullOrWhiteSpace(o)) != 0)
                {
                    ModelState.AddModelError("opponent", string.Format(version.Variant.Name + " requires {0} players, so you must specify {1} opponent{2}.", version.Variant.PlayerCount, version.Variant.PlayerCount - 1, version.Variant.PlayerCount == 2 ? string.Empty : "s"));
                    return(false);
                }

                if (opponent.FirstOrDefault(o => string.Equals(o.Trim(), User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)) != null)
                {
                    ModelState.AddModelError("opponent", "You cannot enter your own name as an opponent.");
                    return(false);
                }

                opponentUsers = new List <User>(opponent.Length);
                foreach (var o in opponent)
                {
                    User u = users.GetByName(o.Trim());
                    if (u == null)
                    {
                        ModelState.AddModelError("opponent", "Not a valid user name: " + o);
                        return(false);
                    }

                    if (opponentUsers.FirstOrDefault(x => string.Equals(x.Name, u.Name, StringComparison.InvariantCultureIgnoreCase)) != null)
                    {
                        ModelState.AddModelError("opponent", "You cannot enter the same opponent multiple times");
                        return(false);
                    }

                    opponentUsers.Add(u);
                }
            }

            return(true);
        }
示例#22
0
        public string CalculateGlobalDirectionDiagram(VariantVersion version)
        {
            var directions = new SortedList <string, GlobalDirInfo>();

            var board = GetDefinition(version).Board;

            foreach (XmlNode fromCell in board.SelectNodes("cell"))
            {
                // read path attr for X & Y positions
                var   fromCellPath = fromCell.Attributes["path"].Value.Substring(1).Split(space, 3);
                float fromCellX, fromCellY;
                if (!float.TryParse(fromCellPath[1], out fromCellY) || fromCellPath[0].Length < 2 || !float.TryParse(fromCellPath[0], out fromCellX))
                {
                    continue;
                }

                foreach (XmlNode link in fromCell.ChildNodes)
                {
                    var dir        = link.Attributes["dir"].Value;
                    var toCellName = link.Attributes["to"].Value;

                    var toCell = board.SelectSingleNode(string.Format("cell[@id='{0}']", toCellName));
                    if (toCell == null)
                    {
                        if (!directions.ContainsKey(dir))
                        {
                            directions[dir] = new GlobalDirInfo(dir, 0);
                        }
                        continue;
                    }

                    // read path attr for X & Y positions
                    var   toCellPath = toCell.Attributes["path"].Value.Split(space, 3);
                    float toCellX, toCellY;
                    if (!float.TryParse(toCellPath[1], out toCellY) || !float.TryParse(toCellPath[0].Substring(1), out toCellX))
                    {
                        if (!directions.ContainsKey(dir))
                        {
                            directions[dir] = new GlobalDirInfo(dir, 0);
                        }
                        continue;
                    }

                    var dx = toCellX - fromCellX;
                    var dy = toCellY - fromCellY;

                    if (!directions.ContainsKey(dir))
                    {
                        directions[dir] = new GlobalDirInfo(dir)
                        {
                            FirstDX = dx, FirstDY = dy
                        }
                    }
                    ;

                    var direction = directions[dir];
                    direction.Num++;
                    direction.DX += dx;
                    direction.DY += dy;
                }
            }

            var svgDoc = new XmlDocument();

            svgDoc.AppendChild(svgDoc.CreateElement("svg"));

            // add a <defs> section containing an arrowhead marker
            var defs = svgDoc.CreateElement("defs");

            defs.InnerXml = @"<marker id=""arrowhead"" viewbox=""0 0 10 10"" refX=""1"" refY=""5"" markerWidth=""6"" markerHeight=""6"" orient=""auto""><path d=""M 0 0 L 10 5 L 0 10 z"" /></marker>
<marker id=""arrowhead_from"" viewbox=""0 0 10 10"" refX=""1"" refY=""5"" markerWidth=""6"" markerHeight=""6"" orient=""auto""><path d=""M 0 0 L 10 5 L 0 10 z"" /></marker>
<marker id=""arrowhead_to"" viewbox=""0 0 10 10"" refX=""1"" refY=""5"" markerWidth=""6"" markerHeight=""6"" orient=""auto""><path d=""M 0 0 L 10 5 L 0 10 z"" /></marker>";
            svgDoc.DocumentElement.AppendChild(defs);

            var attr = svgDoc.CreateAttribute("xmlns");

            attr.Value = "http://www.w3.org/2000/svg";
            svgDoc.DocumentElement.Attributes.Append(attr);

            attr       = svgDoc.CreateAttribute("id");
            attr.Value = "indicator";
            svgDoc.DocumentElement.Attributes.Append(attr);

            attr       = svgDoc.CreateAttribute("viewbox");
            attr.Value = "-120 -120 240 240";
            svgDoc.DocumentElement.Attributes.Append(attr);

            // the elements should be written out here sorted by their directions, such that they come out in a clockwise order (this isn't for the diagram itself, but for the edit groups)

            const float tolerance = 0.01f;

            foreach (var kvp in directions)
            {
                var dir = kvp.Value;

                if (dir.Num > 1)
                {
                    dir.DX /= dir.Num;
                    dir.DY /= dir.Num;
                }

                if (Math.Abs(dir.DX) < tolerance && Math.Abs(dir.DY) < tolerance)
                {
                    dir.DX = dir.FirstDX; dir.DY = dir.FirstDY;
                }
            }


            foreach (var dir in directions.Values.OrderBy(dir => dir.Angle))
            {
                Console.WriteLine("{0}, {1}", dir.Name, dir.Angle);
                var magnitude = (float)Math.Sqrt(dir.DX * dir.DX + dir.DY * dir.DY);
                dir.DX /= magnitude; dir.DY /= magnitude;

                var line = svgDoc.CreateElement("line");
                svgDoc.DocumentElement.AppendChild(line);

                attr       = svgDoc.CreateAttribute("x1");
                attr.Value = (dir.DX * 10).ToString("0.#");
                line.Attributes.Append(attr);

                attr       = svgDoc.CreateAttribute("y1");
                attr.Value = (dir.DY * 10).ToString("0.#");
                line.Attributes.Append(attr);

                attr       = svgDoc.CreateAttribute("x2");
                attr.Value = (dir.DX * 100).ToString("0.#");
                line.Attributes.Append(attr);

                attr       = svgDoc.CreateAttribute("y2");
                attr.Value = (dir.DY * 100).ToString("0.#");
                line.Attributes.Append(attr);

                attr       = svgDoc.CreateAttribute("class");
                attr.Value = "marker";
                line.Attributes.Append(attr);

                attr       = svgDoc.CreateAttribute("dir");
                attr.Value = dir.Name;
                line.Attributes.Append(attr);

                attr       = svgDoc.CreateAttribute("marker-end");
                attr.Value = "url(#arrowhead)";
                line.Attributes.Append(attr);
            }

            return(svgDoc.OuterXml);
        }
示例#23
0
        public void SaveRelativeDirs(VariantVersion version, string relData)
        {
            var definition = GetDefinition(version);
            var root       = definition.Dirs;

            if (root == null)
            {
                root = definition.Dirs = definition.CreateElement("dirs");
            }
            else
            {
                // clear existing relative directions
                var existingDirs = root.SelectNodes("relative");
                foreach (XmlNode dir in existingDirs)
                {
                    dir.ParentNode.RemoveChild(dir);
                }
            }

            var relativeDirData = new SortedList <string, List <Tuple <string, string> > >();

            var relLink = relData.Split(outerSep, StringSplitOptions.RemoveEmptyEntries);

            foreach (string link in relLink)
            {
                var linkParts = link.Split(innerSep, 3);
                if (linkParts.Length != 3)
                {
                    continue;
                }

                string from   = linkParts[0];
                string relDir = linkParts[1];
                string to     = linkParts[2];

                List <Tuple <string, string> > linksForThisDir;
                if (!relativeDirData.TryGetValue(relDir, out linksForThisDir))
                {
                    linksForThisDir = new List <Tuple <string, string> >();
                    relativeDirData.Add(relDir, linksForThisDir);
                }

                linksForThisDir.Add(new Tuple <string, string>(from, to));
            }

            foreach (var kvp in relativeDirData)
            {
                var relDirNode = definition.CreateElement("relative");
                relDirNode.Attributes.Append(definition.CreateAttribute("name", kvp.Key));

                foreach (var link in kvp.Value)
                {
                    var linkNode = definition.CreateElement("link");
                    linkNode.Attributes.Append(definition.CreateAttribute("from", link.Item1));
                    linkNode.Attributes.Append(definition.CreateAttribute("to", link.Item2));
                    relDirNode.AppendChild(linkNode);
                }

                root.PrependChild(relDirNode);
            }
            definition.Dirs      = root;
            version.LastModified = DateTime.Now;
            Entities.SaveChanges();
        }
示例#24
0
        public XmlNode GetPieceDefinitionXML(VariantVersion version)
        {
            var definition = GetDefinition(version);

            return(definition.Pieces);
        }