public void NTest_check_fullyConnected_notConnected() { Node n1 = new Node("" + 0, 1); Node n2 = new Node("" + 1, 1); Node n3 = new Node("" + 2, 1); Node n4 = new Node("" + 3, 1); Node n5 = new Node("" + 4, 1); n1.connect(n2); n1.connect(n3); n1.connect(n4); n1.connect(n5); Assert.IsTrue(n1.isFullyConnected()); }
/* 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)); } } }