public void MSTest_disconnectBridge() { Bridge bridge = new Bridge("bridge 4"); Node node1 = new Node(); Node node2 = new Node(); Node node3 = new Node(); Node node4 = new Node(); bridge.connectToNodeOfNextZone(node1); bridge.connectToNodeOfNextZone(node2); bridge.connectToNodeOfSameZone(node3); bridge.connectToNodeOfSameZone(node4); Dungeon d = new Dungeon(); Player P = new Player(); P.location = bridge; P.dungeon = d; d.zone = new Dictionary <int, List <Node> >(); d.zone[4] = new List <Node>(); d.zone[4].Add(bridge); d.zone[4].Add(node3); d.zone[4].Add(node4); Item x = new Crystal("cryst1"); P.bag.Add(x); P.use(x); Assert.IsTrue(bridge.GetFromNodes.Count == 2); Assert.IsTrue(bridge.neighbors.Contains(node1)); Assert.IsTrue(bridge.neighbors.Contains(node2)); Assert.IsTrue(!bridge.neighbors.Contains(node3)); Assert.IsTrue(!bridge.neighbors.Contains(node4)); Assert.IsTrue(!node3.neighbors.Contains(bridge)); Assert.IsTrue(!node4.neighbors.Contains(bridge)); }
public void MSTest_connect_to_same_zone() { Bridge bridge = new Bridge("bridgeID"); Node node1 = new Node("node1"); bridge.connectToNodeOfSameZone(node1); Assert.IsTrue(bridge.GetFromNodes.Contains(node1)); }
// connects the correct side of the bridge to a given node public void connectBridge(Bridge thisBrige, Node toNode, bool sameZone) { if (sameZone) { thisBrige.connectToNodeOfSameZone(toNode); } else { thisBrige.connectToNodeOfNextZone(toNode); } }
public void Level_Simple() { //tets a simple graph Dungeon a = new Dungeon(1, 1); a.graph.Clear(); a.startNode = null; a.exitNode = null; Node[] xs = new Node[2]; //level 1 xs[0] = new Node("0"); xs[0].nodeLevel = 1; a.startNode = xs[0]; Bridge b1 = new Bridge("2"); b1.nodeLevel = 1; xs[1] = new Node("1"); xs[1].nodeLevel = 2; b1.connectToNodeOfSameZone(xs[0]); b1.connectToNodeOfSameZone(xs[1]); a.exitNode = xs[1]; a.bridges = new Bridge[] { b1 }; a.dungeon_size = 3; a.graph.Add(xs[0]); a.graph.Add(b1); a.graph.Add(xs[1]); //startnode - bridge - exitnode (startnode and bridge are lvl 1 and exitnode lvl 0) foreach (Node n in Predicates.reachableNodes(a.startNode)) { Assert.AreEqual(n.nodeLevel, a.level(n)); } }
public void MSTest_use_crystal_disconnectbridge() { Bridge bridge = new Bridge("bridge"); Node start = new Node("start"); Node final = new Node("final"); Dungeon dungeon = new Dungeon(1, 1); Player player = new Player(); Item crystal = new Crystal("crystal"); player.bag.Add(crystal); player.location = bridge; player.dungeon = dungeon; bridge.connectToNodeOfSameZone(start); bridge.connectToNodeOfNextZone(final); player.use(crystal); Assert.IsFalse(dungeon.startNode.neighbors.Contains(start)); Assert.IsTrue(dungeon.startNode.neighbors.Contains(final)); }
public void Crystal_Use_OnBridge() { Node N0 = new Node("N0"); Bridge N1 = new Bridge("N1"); Node N2 = new Node("N2"); Node N3 = new Node("N3"); N1.connectToNodeOfSameZone(N0); N1.connectToNodeOfNextZone(N2); N1.connectToNodeOfNextZone(N3); N3.connect(N2); Predicates utils = new Predicates(); List <Node> mockDungeon = utils.reachableNodes(N1); Assert.IsTrue(mockDungeon.Contains(N0)); player.dungeon = new Dungeon(1, 1); player.location = N1; Crystal crystal = new Crystal("crystal1"); player.bag.Add(crystal); player.use(crystal); mockDungeon = utils.reachableNodes(N1); Assert.IsFalse(player.bag.Contains(crystal)); Assert.IsTrue(player.accelerated); Assert.IsFalse(mockDungeon.Contains(N0)); Assert.IsNull(player.name); Assert.AreEqual(0, player.HP); Assert.AreEqual(5u, player.AttackRating); Assert.AreEqual(100, player.HPbase); Assert.AreEqual(0u, player.KillPoint); foreach (Node node in mockDungeon) { Console.WriteLine(node.id); } }
/*Tuple contains the remaining connections from the bridge, * the amount of nodes, and the total amount of connections.*/ private Tuple <int, int, int> makeSection(Node start, int startc, ref int level) { Bridge b = new Bridge(level.ToString()); Bridge bstart = start as Bridge; if (startc == 1) //can only be directly connected to a bridge { level++; b.connectToNodeOfSameZone(start); if (bstart != null) { bstart.connectToNodeOfNextZone(b); bstart.disconnect(b); } if (level > difficultyLevel + 1) { exitNode = new Node(b); } else { bridges[level - 2] = b; } return(Tuple.Create(rng.Next(1, 4), 1, 1)); } HashSet <int> open = new HashSet <int>(); List <Node> nodes = new List <Node>(); List <int> conns = new List <int>(); int totalConns = 0; open.Add(0); nodes.Add(start); conns.Add(startc); int index; while (open.Count > 1 || open.Contains(0)) { Node n = new Node(); index = nodes.Count; open.Add(index); nodes.Add(n); conns.Add(rng.Next(1, 5)); for (int i = 0; i < index; i++) { if (open.Contains(i) && conns.Sum() > open.Count) { totalConns++; nodes[i].connect(n); conns[i]--; if (conns[i] == 0) { open.Remove(i); } conns[index]--; if (conns[index] == 0) { open.Remove(index); break; } } } } if (bstart != null) { bstart.toNodes = bstart.neighbors.Except(bstart.fromNodes).ToList(); } index = open.Single(); foreach (Node nd in shortestpath(start, nodes[index]) .Where(m => m == nodes[index] || p.isBridge(start, nodes[index], m))) { level++; if (level > difficultyLevel + 1) { exitNode = nd; exitNode.id = "exit"; break; } else { var nb = nd.neighbors; while (nb.Count > 0) { Node m = nb[0]; m.disconnect(nd); if (p.isReachable(start, m)) { b.connectToNodeOfSameZone(m); } else { b.connectToNodeOfNextZone(m); } } bridges[level - 2] = b; b = new Bridge(level.ToString()); } } return(Tuple.Create(conns[index], nodes.Count - 1, totalConns)); }
/* To create a new dungeon with the specified difficult level and capacity multiplier */ //TO-DO: check average connectivity predicate //TO-DO: improve the algorithm for building connections between nodes in the same zone public Dungeon(uint level, uint nodeCapacityMultiplier, Random random) { Logger.log("Creating a dungeon of difficulty level " + level + ", node capacity multiplier " + nodeCapacityMultiplier + "."); difficultyLevel = level; //assign dungeon difficulty level bridges = new List <Bridge>(); //List of bridges initialized predicates = new Predicates(); zones = new List <Zone>(); //initialize the zones M = nodeCapacityMultiplier; //initialize node capacity multiğlier int numberOfNodesInZone = 0; int connected = 0; //every node is named with its zone number followed by its number in a zone (nodeId = preId+lastId) string preId, lastId, nodeId = ""; startNode = new Node("" + 10, 1); //start node id is set Logger.log("Set startNode Id: 10"); for (int i = 1; i < level + 1; i++) //i signifies zone level, for each zone { Zone newZone = new Zone(i, nodeCapacityMultiplier); //create a new zone zones.Add(newZone); //add it in dungeon.zones list Logger.log("Creating level " + i); preId = "" + i; // preId is zone level numberOfNodesInZone = random.Next(2, 5); //randomly decide between 2-4 nodes in a zone //if you change number of nodes can be in a zone, be careful with the dependent statements below Logger.log("Number of nodes in zone " + i + " is " + numberOfNodesInZone); for (int j = 1; j <= numberOfNodesInZone; j++) //for each node in a zone { //create and add nodes to the list nodesInZone lastId = "" + j; nodeId = preId + lastId; //merge preId and lastId to create nodeId Node newNode = new Node(nodeId, i); //create node Logger.log("Created node with id " + nodeId); newZone.nodesInZone.Add(newNode); //add node to the list } //zone's nodesInZone list stores every node in this zone int numberOfNodesToConnect; // temp variable to decide how many nodes to connect for startNode or for bridges Node zoneFirstNode; //holds start node or starting bridge for the zone //(starting bridge for a zone is the bridge which is connecting it to the previous zone) if (i == 1) //for the first level { // connect start node to some nodes in the zone zoneFirstNode = startNode; numberOfNodesToConnect = random.Next(1, numberOfNodesInZone + 1); //randomly decide btw 1-4 nodes //rnd operation is exclusive for the max number, numberofNodesInZone can be 4 at most, thus it is safe this way Logger.log("Connecting startNode to " + numberOfNodesToConnect + " nodes in the zone "); for (int j = 0; j < numberOfNodesToConnect; j++) //for each nodes to connect { //connect them with the start node int nodeIndex = random.Next(0, numberOfNodesInZone); //randomly get node index to connect while (startNode.alreadyConnected(newZone.nodesInZone.ElementAt(nodeIndex))) { //if the chosen node is already connected nodeIndex = random.Next(0, numberOfNodesInZone); //choose a new one } startNode.connect(newZone.nodesInZone.ElementAt(nodeIndex)); //connect start node with that node Logger.log("Connected to node " + newZone.nodesInZone.ElementAt(j).id); } } else { //connect bridge to some nodes in the next zone Bridge startBridge = bridges.ElementAt(i - 2); //bridge is already created in previous loop zoneFirstNode = (Node)startBridge; int maxConnect = 4 - startBridge.neighbors.Count; //maximum number of connections that bridge can make if (numberOfNodesInZone < maxConnect) //maximum number of connections are constrained by { maxConnect = numberOfNodesInZone; //number of zones in the zone } numberOfNodesToConnect = random.Next(1, maxConnect + 1); //Decide how many connections it should make Logger.log("Connecting bridge " + startBridge.id + " to " + numberOfNodesToConnect + " nodes in the next zone "); for (int j = 0; j < numberOfNodesToConnect; j++) { //connect them with the bridge node int nodeIndex = random.Next(0, numberOfNodesInZone); //randomly decide the node index while (startBridge.alreadyConnected(newZone.nodesInZone.ElementAt(nodeIndex))) { nodeIndex = random.Next(0, numberOfNodesInZone); } startBridge.connectToNodeOfNextZone(newZone.nodesInZone.ElementAt(nodeIndex)); //connect bridge with the next zone Logger.log("Connected to node " + newZone.nodesInZone.ElementAt(j).id); } } Logger.log("Connecting nodes in the same zone"); //connect nodes in the same zone //TO-DO improve the algorithm //Currently it exits the algorithm once every node is accessible from the starting node of the zone while (!allReachable(newZone.nodesInZone, zoneFirstNode)) //while there exists not reachable nodes { Node n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); //randomly choose node1 while (n1.isFullyConnected()) //if it is fully connected node { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); //choose another one } Node n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); //randomly select node2 while (n2.isFullyConnected() || n2.id == n1.id || n2.alreadyConnected(n1)) //make sure it is not fully connected, not same as node1, not already connected with node1 { n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n1.connect(n2); Logger.log("Nodes " + n1.id + " " + n2.id + " are connected"); } List <Node> listOfNotFullNodes = new List <Node>(); //get list of not fully connected nodes in the zone to consider connections for (int j = 0; j < newZone.nodesInZone.Count; j++) { Node nd = newZone.nodesInZone.ElementAt(j); if (!nd.isFullyConnected()) { listOfNotFullNodes.Add(nd); } } Logger.log("Creating list of not full nodes, number of not full nodes " + listOfNotFullNodes.Count); //Connect last node to the zone, either a bridge or the exit node int min = 1; int max; if (i == level) { // last zone //connect exit node lastId = "" + (numberOfNodesInZone + 1); nodeId = preId + lastId; //create id of the exit node exitNode = new Node(nodeId, i); //create exit node Logger.log("Last zone is finished, exit node id is set to " + nodeId); max = 4; //max number of connections that node can have if (listOfNotFullNodes.Count < 4) { max = listOfNotFullNodes.Count; //can make at most listOfNotFullNodes.Count number of connections } numberOfNodesToConnect = random.Next(min, max + 1); //randomly decide number of nodes to connect for (int j = 0; j < numberOfNodesToConnect; j++) //connect exit node to that number of nodes { exitNode.connect(listOfNotFullNodes.ElementAt(j)); //can be randomized Logger.log("Connected to node " + listOfNotFullNodes.ElementAt(j).id); } } else { //connect to end bridge //a bridge can be connected to at minimum 1 and at maximum 3 nodes lastId = "" + (numberOfNodesInZone + 1); nodeId = preId + lastId; //create bridge id Bridge endBridge = new Bridge(nodeId, i); //create the bridge bridges.Add(endBridge); //add it to bridges list to access it in the next loop iteration Logger.log("A new bridge is created with id " + nodeId); max = 3; //since a bridge should already have at least 1 connection to the other zone //max number of connections it can make can not be more than 3 if (listOfNotFullNodes.Count < 3) { max = listOfNotFullNodes.Count; //can make at most listOfNotFullNodes.Count number of connections } numberOfNodesToConnect = random.Next(min, max + 1); //decide number of nodes to connect for (int j = 0; j < numberOfNodesToConnect; j++) //connect it to that number of nodes { endBridge.connectToNodeOfSameZone(listOfNotFullNodes.ElementAt(j)); //not randomized Logger.log("Connected to node " + listOfNotFullNodes.ElementAt(j).id); } //end bridge is also connected } //Ensure the average connectivity if (i == 1) { Node n1, n2; connected = startNode.neighbors.Count; for (int j = 0; j < numberOfNodesInZone; j++) { connected += newZone.nodesInZone.ElementAt(j).neighbors.Count; } while (Convert.ToDouble(connected / (numberOfNodesInZone + 1)) > 3) { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); while (n1.neighbors.Count <= 1) { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); while (n2.neighbors.Count <= 1 || n2.id == n1.id || !n2.alreadyConnected(n1)) { n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n1.disconnect(n2); Logger.log("Nodes " + n1.id + " " + n2.id + " are disconnected"); connected -= 2; } } else if (i == level) { Node n1, n2; connected = exitNode.neighbors.Count; connected += bridges.ElementAt(i - 2).neighbors.Count; for (int j = 0; j < numberOfNodesInZone; j++) { connected += newZone.nodesInZone.ElementAt(j).neighbors.Count; } while (Convert.ToDouble(connected / (numberOfNodesInZone + 2)) > 3) { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); while (n1.neighbors.Count <= 1) { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); while (n2.neighbors.Count <= 1 || n2.id == n1.id || !n2.alreadyConnected(n1)) { n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n1.disconnect(n2); Logger.log("Nodes " + n1.id + " " + n2.id + " are disconnected"); connected -= 2; } } else { Node n1, n2; connected = bridges.ElementAt(i - 2).neighbors.Count; for (int j = 0; j < numberOfNodesInZone; j++) { connected += newZone.nodesInZone.ElementAt(j).neighbors.Count; } while (Convert.ToDouble(connected / (numberOfNodesInZone + 1)) > 3) { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); while (n1.neighbors.Count <= 1) { n1 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); while (n2.neighbors.Count <= 1 || n2.id == n1.id || !n2.alreadyConnected(n1)) { n2 = newZone.nodesInZone.ElementAt(random.Next(0, numberOfNodesInZone)); } n1.disconnect(n2); Logger.log("Nodes " + n1.id + " " + n2.id + " are disconnected"); connected -= 2; } } //pass to next zone Logger.log("Passing to next zone"); } //Add startnode, bridges and endnode foreach (Zone z in zones) { if (z.id == 1) //first zone, add start node { z.nodesInZone.Add(startNode); } else if (z.id == level) //last zone, add end node { z.nodesInZone.Add(exitNode); } if (z.id != level) //in middle zones, add their bridges { z.nodesInZone.Add(bridges.ElementAt(z.id - 1)); } } }
public void Level_Test_Groot() { //test a bigger graph (figure 1 from project description) Dungeon a = new Dungeon(1, 1); a.graph.Clear(); a.startNode = null; a.exitNode = null; Node[] xs = new Node[10]; //startnode xs[0] = new Node("0"); xs[0].nodeLevel = 1; a.startNode = xs[0]; xs[1] = new Node("1"); xs[1].nodeLevel = 1; xs[2] = new Node("2"); xs[2].nodeLevel = 1; xs[3] = new Node("3"); xs[3].nodeLevel = 1; xs[4] = new Node("4"); xs[4].nodeLevel = 1; Bridge b1 = new Bridge("10"); b1.nodeLevel = 1; xs[0].connect(xs[1]); xs[0].connect(xs[3]); xs[0].connect(xs[2]); xs[2].connect(xs[1]); xs[2].connect(xs[3]); xs[3].connect(xs[4]); b1.connectToNodeOfSameZone(xs[1]); b1.connectToNodeOfSameZone(xs[2]); //level 2 xs[5] = new Node("5"); xs[5].nodeLevel = 2; xs[6] = new Node("6"); xs[6].nodeLevel = 2; b1.connectToNodeOfNextZone(xs[5]); b1.connectToNodeOfNextZone(xs[6]); Bridge b2 = new Bridge("11"); b2.nodeLevel = 2; xs[5].connect(xs[6]); b2.connectToNodeOfSameZone(xs[5]); b2.connectToNodeOfSameZone(xs[6]); //level 0 xs[7] = new Node("7"); xs[7].nodeLevel = 3; b2.connectToNodeOfNextZone(xs[7]); xs[8] = new Node("8"); xs[8].nodeLevel = 3; b2.connectToNodeOfNextZone(xs[8]); //exit node xs[9] = new Node("9"); xs[9].nodeLevel = 3; xs[9].connect(xs[7]); xs[9].connect(xs[8]); a.startNode = xs[0]; a.exitNode = xs[9]; a.bridges = new Bridge[] { b1, b2 }; for (int i = 0; i < 10; i++) { a.graph.Add(xs[i]); } a.graph.Add(b1); a.graph.Add(b2); a.dungeon_size = 12; foreach (Node n in Predicates.reachableNodes(a.startNode)) { Assert.AreEqual(n.nodeLevel, a.level(n)); } }