public void DisconnectTest() { Dungeon a = new Dungeon(10, 1); Random rnd = RandomGenerator.rnd; int i = rnd.Next(a.bridges.Length); string bridgeid = a.bridges[i].id; //maak lijst van nodes die allemaal behouden moeten worden List <string> keep = new List <string>(); foreach (Node n in Predicates.reachableNodes(a.startNode)) { if (a.level(n) > a.level(a.bridges[i]) || a.level(n) == 0) { keep.Add(n.id); } } keep.Add(a.bridges[i].id); a.disconnect(a.bridges[i]); foreach (Node n in Predicates.reachableNodes(a.startNode)) { Assert.IsTrue(keep.Contains(n.id)); } }
public void MSTest_level() { Node node = new Node(); Bridge bridge = new Bridge("bridge 4"); Dungeon d = new Dungeon(); uint nodeLevel = d.level(node); uint bridgeLevel = d.level(bridge); Assert.IsTrue(nodeLevel == 0); Assert.IsTrue(bridgeLevel == 4); }
/* Move the pack to an adjacent node. */ public void move(Node u) { if (u == location) { Logger.log("Pack" + id + " doesn't move."); return; } if (!location.neighbors.Contains(u)) { throw new ArgumentException(); } int capacity = (int)(dungeon.M * (dungeon.level(u) + 1)); // count monsters already in the node: foreach (Pack Q in u.packs) { capacity = capacity - Q.members.Count; } // capacity now expresses how much space the node has left if (members.Count > capacity) { Logger.log("Pack " + id + " is trying to move to a full node " + u.id + ", but this would cause the node to exceed its capacity. Rejected."); return; } location.packs.Remove(this); location = u; u.packs.Add(this); }
public void PopulateDungeon(int monsters, ref int monsterHP, Dungeon dungeon) { int monstersLeft = monsters; int l = dungeon.zone.Count + 1; for (int i = 1; i < l; i++) { int rMax = (int)dungeon.M + 1; List <Node> curZone = dungeon.zone[i]; int monstersThisZone = (2 * i * monsters) / (int)((dungeon.difficultyLevel + 2) * (dungeon.difficultyLevel + 1)); if (monstersThisZone > monstersLeft) { monstersThisZone = monstersLeft; monstersLeft = 0; } else { monstersLeft -= monstersThisZone; } //if (monstersThisZone > monstersLeft) // monstersThisZone = monstersLeft; //monstersLeft -= monstersThisZone; int j = 1; string idPrefix = "Pack-" + i + "."; while (monstersThisZone > 0) { if (rMax > monstersThisZone) { rMax = monstersThisZone; } int nPack = r.Next(1, rMax); int index = r.Next(curZone.Count); if (curZone[index] == dungeon.exitNode) { continue; //not allowed to drop in exitnode, skip } int capacity = (int)(dungeon.M * (dungeon.level(curZone[index]) + 1)); // count monsters already in the node: foreach (Pack Q in curZone[index].packs) { capacity = capacity - Q.members.Count; } if (capacity >= nPack) //if there is enough space, make and drop new pack { Pack pack = new Pack(idPrefix + j, (uint)nPack); j++; monstersThisZone -= nPack; pack.location = curZone[index]; pack.dungeon = dungeon; pack.zone = i; curZone[index].packs.Add(pack); monsterHP += pack.startingHP; } } } }
// parameter = visit node public void Move(Node move) { if (move == null) { throw new ArgumentException(); } Node old_location = this.location; if (dungeon.level(old_location) != dungeon.level(move)) { Console.WriteLine("You entered zone: " + dungeon.level(move)); undo_alert_packs(old_location, move); //checks if it is necessary to undo alert packs (Ralert rule) enter_last_zone(move); //checks if it is really the last zone and apply RendZone rule } if (move != null && this.location.neighbors.Contains(move)) { this.location.contested = false; this.location = move; move.visited = true; //Pick up items. foreach (Item potion in this.location.items.ToList()) { if (potion is HealingPotion) { Console.WriteLine("You found a potion with {0} healing. Added to bag.", (potion as HealingPotion).HPvalue); } else { Console.WriteLine("You found a crystal! Added to bag."); } this.location.items.Remove(potion); this.bag.Add(potion); } if (this.location.packs.Count > 0) { this.location.contested = true; alert_packs(this.location); //(Ralert rule) } } else { throw new ArgumentException(); } }
public void MStest_move_with_insufficient_capacity() { Dungeon d = new Dungeon(5); Pack p = new Pack("pid", 3); Pack q = new Pack("qid", (d.M * (d.level(d.zone[1][1]) + 1))); p.dungeon = d; q.dungeon = d; p.location = d.zone[1][0]; q.location = d.zone[1][1]; d.zone[1][0].packs.Add(p); d.zone[1][1].packs.Add(q); p.move(d.zone[1][1]); Assert.IsTrue(p.location == d.zone[1][0]); }
public Node getRandomValidNeighbour(Dungeon d) { List <Node> candidates = new List <Node>(); foreach (Node n in this.location.neighbors.ToList()) { if (n.CountCreatures() + this.members.Count < n.Capacity(d) && d.level(n) == d.level(this.location) && n != dungeon.exitNode) { candidates.Add(n); } } if (candidates.Count() == 0) { return(this.location); } else { return(candidates.GetRandomItem()); } }
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)); } }
/* Move the pack to an adjacent node. */ public void move(Node u, Node playerlocation = null) { if (u == location) { return; } if (!location.neighbors.Contains(u) || u == null) { throw new ArgumentException(); } uint capacity = dungeon.M * (dungeon.level(u) + 1); if (u.CountCreatures() + this.members.Count() >= capacity) { Logger.log("Pack " + id + " is trying to move to an already full node " + u.id + ". Rejected."); //throw new ArgumentException(); } else if (u == dungeon.exitNode) { Logger.log("Pack " + id + " is trying to move to the exit node, rejected."); // throw new ArgumentException(); } else { location.packs.Remove(this); location = u; if (location == playerlocation && members.Count > 0) { location.contested = true; } foreach (Monster m in members.ToList()) { m.location = u; } u.packs.Add(this); } }
/* Move the pack to an adjacent node. */ public void move(Node u) { if (!location.neighbors.Contains(u)) { throw new ArgumentException(); } // pack can't move to a different zone if (location.zoneNumber != u.zoneNumber) { return; } int capacity = (int)(dungeon.M * (dungeon.level(u) + 1)); // count monsters already in the node: foreach (Pack Q in u.packs) { capacity = capacity - Q.members.Count; } // capacity now expresses how much space the node has left if (members.Count > capacity) { Logger.log(id + " is trying to move to a full node " + u.id + ", but this would cause the node to exceed its capacity. Rejected."); return; } u.packs.Add(this); string prevLocation = location.id; location.packs.Remove(this); location = u; foreach (Monster m in members) { m.location = location; } Logger.log(id + " moves from " + prevLocation + " to " + location.id + "."); }
/** * Move the pack to an adjacent node. * @param name="u" node should be adjacent */ public void Move(Node u) { if (!location.neighbors.Contains(u)) { throw new ArgumentException(); } int capacity = (int)(dungeon.M * (dungeon.level(u) + 1)); //each zone has a specified capacity // count monsters already in the node: foreach (Pack Q in location.packs) //for each pack in the node { capacity = capacity - Q.members.Count; //decrease the capacity by number of pack members } // capacity now expresses how much space the node has left if (members.Count > capacity) { Logger.log("Pack " + id + " is trying to move to a full node " + u.id + ", but this would cause the node to exceed its capacity. Rejected."); return; } //else move is successful this.location = u; u.packs.Add(this); Logger.log("Pack " + id + " moves to the node " + u.id + ". Not rejected."); }
public void spawnMonsters(uint numberOfMonsters, uint difficultyLevel) { Random r = RandomGenerator.rnd; List <Node> availableNodes = Predicates.reachableNodes(dungeon.startNode); Logger.log("This dungeon consists of " + availableNodes.Count + " nodes."); uint monstersLeft = numberOfMonsters; double monstersinLevel = 0; uint packID = 0; for (uint i = 1; i < difficultyLevel; i++) { List <Node> availableNodesinLevel = new List <Node>(); foreach (Node n in availableNodes.ToList()) { if (dungeon.level(n) == i) { availableNodesinLevel.Add(n); } } monstersinLevel = Math.Round((2 * i * (double)numberOfMonsters / ((difficultyLevel + 2) * (difficultyLevel + 1)))); while (monstersinLevel > 0) { uint capacityLevel = availableNodesinLevel[0].Capacity(dungeon); foreach (Node nd in availableNodesinLevel.ToList()) { int creatureCount = nd.CountCreatures(); int space = (int)capacityLevel - creatureCount; if (space == 0) { availableNodesinLevel.Remove(nd); } if (availableNodesinLevel.Count() == 0) { throw new GameCreationException("Too many monsters, not enough nodes"); } int spawnX = r.Next(0, Math.Min(space, (int)monstersinLevel) + 1); if (spawnX == 0) { continue; //We increase randomness by potentially skipping a node while placing packs } monstersinLevel -= (double)spawnX; monstersLeft -= (uint)spawnX; Pack pack = new Pack(packID++.ToString(), (uint)spawnX, nd, dungeon); nd.packs.Add(pack); dungeon.alivePacks.Add(pack); } //Console.WriteLine("{0} monsters in level. {1} monsters left", monstersinLevel, monstersLeft); } } List <Node> availableNodesinExit = new List <Node>(); foreach (Node n in availableNodes.ToList()) { if (dungeon.level(n) == dungeon.level(dungeon.exitNode)) { availableNodesinExit.Add(n); } } while (monstersLeft > 0) { uint capacityLevel = dungeon.M * (dungeon.level(availableNodesinExit[0]) + 1); foreach (Node nd in availableNodesinExit.ToList()) { int creatureCount = nd.CountCreatures(); int space = (int)capacityLevel - creatureCount; if (space == 0) { availableNodesinExit.Remove(nd); } if (availableNodesinExit.Count() == 0) { throw new GameCreationException("Too many monsters, not enough nodes"); } int spawnX = r.Next(0, Math.Min(space, (int)monstersLeft) + 1); if (spawnX == 0) { continue; } monstersLeft -= (uint)spawnX; Pack pack = new Pack(packID++.ToString(), (uint)spawnX, nd, dungeon); pack.location = nd; nd.packs.Add(pack); dungeon.alivePacks.Add(pack); } //Console.WriteLine("Spreading monsters in last zone {0} monsters left", monstersLeft); } }
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)); } }
/*Node level should always be 0, Dungeon size is irrelevant so no FsCheck.*/ public void TestNodeLevel() { var d = new Dungeon(1, 1); Assert.Zero(d.level(new Node())); }
public void NTest_located_Level() { Node n1 = new Node("1", 1); Assert.Equals(dungeon.level(n1), 1); }
public uint Capacity(Dungeon d) { return(d.M * (d.level(this) + 1)); }
// takes a Command and processes it according to the game rules private void processPlayerInput(Command userCommand) { // pick up any item if (player.location.items.Count != 0) { for (int i = player.location.items.Count - 1; i >= 0; i--) { Item item = player.location.items[i]; player.bag.Add(item); player.location.items.Remove(item); } } // move to node if (userCommand.action == Command.Action.Move) { // old player location not contested anymore player.location.isContested = false; player.move(userCommand.moveTo); // if player left alert zone, reset alert zone if (dungeon.alertZone != player.location.zoneNumber) { dungeon.alertZone = -1; } } // attack if (userCommand.action == Command.Action.Attack) { playerAttacks(player.location); // set alert zone if (dungeon.alertZone != dungeon.level(player.location)) { if (dungeon.alertZone != player.location.zoneNumber) { dungeon.alertZone = player.location.zoneNumber; } } } // flee if (userCommand.action == Command.Action.Flee) { playerFlees(player.location); // if player left alert zone, reset alert zone if (dungeon.alertZone != player.location.zoneNumber) { dungeon.alertZone = -1; } } // use crystal if (userCommand.action == Command.Action.UseCrystal) { Item item = player.bag.Find(i => i is Crystal); player.use(item); items.Remove(item); } // use potion if (userCommand.action == Command.Action.UsePostion) { Item item = player.bag.Find(i => i is HealingPotion); player.use(item); items.Remove(item); } // leave if (userCommand.action == Command.Action.Leave && player.location is Bridge) { // ((Bridge)player.location).disconnectBridge(); } }
/* This creates a player and a random dungeon of the given difficulty level and node-capacity * The player is positioned at the dungeon's starting-node. * The constructor also randomly seeds monster-packs and items into the dungeon. The total * number of monsters are as specified. Monster-packs should be seeded as such that * the nodes' capacity are not violated. Furthermore the seeding of the monsters * and items should meet the balance requirements stated in the Project Document. */ public Game(uint difficultyLevel, uint nodeCapcityMultiplier, uint numberOfMonsters) { player = new Player(); dungeon = new Dungeon(difficultyLevel, nodeCapcityMultiplier); packs = new List <Pack>(); items = new List <Item>(); // Game should have at least one monster. if (numberOfMonsters < 2) { throw new GameCreationException("Not enough monsters. numberOfMonsters should be >= 2"); } // Check if node multiplier is bigger then 1, else dungeon cannot have any monsters. if (nodeCapcityMultiplier <= 0) { throw new GameCreationException("Invalid nodeCapcityMultiplier must be > 0"); } // Check if dungeon is big enough to hold all the monsters. uint maxCapacity = 0; dungeon.allNodes.ForEach(node => maxCapacity += nodeCapcityMultiplier * (dungeon.level(node) + 1)); if (numberOfMonsters > maxCapacity) { throw new GameCreationException("The number of monsters (" + numberOfMonsters + ") exceed dungeon capacity (" + maxCapacity + ")"); } Logger.log("Creating a game of difficulty level " + difficultyLevel + ", node capacity multiplier " + nodeCapcityMultiplier + ", and " + numberOfMonsters + " monsters."); player.dungeon = dungeon; // Player should start at the starting node. player.location = dungeon.startNode; // Get all dungeon bridges. List <Node> bridges = new List <Node>(dungeon.bridges); // Pretend the start and exit node are also a bridge. bridges.Insert(0, dungeon.startNode); bridges.Add(dungeon.exitNode); // The total hp off all monsters, will later be used to determine the amount of healing potions that can be spawned. int totalMonsterHp = 0; // Number of packs created. int packCount = 0; // Number of monsters created. int monsterCount = 0; // Helper function for pack creation. Func <uint, Node, Pack> createPack = new Func <uint, Node, Pack>((numberOfMonstersToCreate, node) => { // Create a pack with the number of monsters. Pack pack = new Pack("Pack" + packCount++, numberOfMonstersToCreate); pack.dungeon = dungeon; pack.location = node; pack.zoneNumber = pack.location.zoneNumber; node.packs.Add(pack); monsterCount += (int)numberOfMonstersToCreate; pack.members.ForEach(member => { member.pack = pack; totalMonsterHp += member.HP; }); packs.Add(pack); return(pack); }); // Distribute packs/monsters in dungeon. for (int level = 0; level <= difficultyLevel; level++) { // The amount of monster allowed in this zone. int monsterPerZone = (int)Math.Floor((2.0 * (level + 1) * numberOfMonsters) / ((difficultyLevel + 2) * (difficultyLevel + 1))); // The last level (zone) does not have to follow the formula above and can get the remaining monsters. if (level == difficultyLevel) { monsterPerZone += ((int)numberOfMonsters - monsterCount) - monsterPerZone; } // All the nodes in the in this zone. (without the start or exit node). List <Node> nodes = Util.getAllNodesBetween(bridges[level], bridges[level + 1]).FindAll(node => node != dungeon.startNode && node != dungeon.exitNode); // For each node in level. for (int i = 0; i < nodes.Count && monsterPerZone > 0; i++) { // The max number of monster that can be on this node. uint nodeCapacityLimit = nodeCapcityMultiplier * (dungeon.level(nodes[i]) + 1); // Subtract the monsters that are already on this node. nodes[i].packs.ForEach(pack => nodeCapacityLimit -= (uint)pack.members.Count); // Take a random number of monster to create for this pack on this node. // But do not exceed the node capacity. uint numberOfMonstersToCreate = (uint)RandomGenerator.rnd.Next((int)(Math.Min(nodeCapacityLimit, monsterPerZone) + 1)); // Check if we can still create a pack, we do not wish to create a pack of zero monsters. if (numberOfMonstersToCreate > 0) { // Subtract the amount of monster spawned from the total monster pool. // This pool should reach zero by the end of the zone. monsterPerZone -= (int)numberOfMonstersToCreate; // Put the pack on then node. createPack(numberOfMonstersToCreate, nodes[i]); } } // Not necessarily all monster should have been created, due to the randomness. // So we just distribute the rest of the monster accordingly. for (int i = 0; i < nodes.Count && monsterPerZone > 0; i++) { // The number of monsters this node can still hold. uint remainingNodeCapacity = nodeCapcityMultiplier * (dungeon.level(nodes[i]) + 1); nodes[i].packs.ForEach(pack => remainingNodeCapacity -= (uint)pack.members.Count); uint numberOfMonstersToCreate = (uint)Math.Min(monsterPerZone, remainingNodeCapacity); // Check if we can still create a pack, we do not wish to create a pack of zero monsters. if (numberOfMonstersToCreate > 0) { monsterPerZone -= (int)numberOfMonstersToCreate; createPack(numberOfMonstersToCreate, nodes[i]); } } // Monsters for this zone should be exactly zero. // If not the zone was to small and the dungeon is invalid. if (monsterPerZone != 0) { throw new GameCreationException("To many monsters to fit in zone!"); } } // Player HP player.HP = Math.Min(player.HPbase, (int)(0.8 * totalMonsterHp)); // All nodes in dungeon without the start and exit node. List <Node> allNodes = dungeon.allNodes.FindAll(node => node != dungeon.startNode && node != dungeon.exitNode); // HP left to spend is the difference between 80% of the total monster HP and the player HP including all possible potions. int hpLeftToSpend = (int)Math.Floor(totalMonsterHp * 0.8) - player.HP; // Minus the HP of possible healing potion already in player bag. //hpLeftToSpend -= (int)player.bag.OfType<HealingPotion>().Sum(item => item.HPvalue); // Generate healing potions. for (int i = 0; ; i++) { HealingPotion potion = new HealingPotion("HP_" + i); // Check if the healing potion will not exceed the maximum amount of HP. if (hpLeftToSpend - potion.HPvalue >= 0) { // Decrease the maximum amount of HP that can still be allocated to healing potions. hpLeftToSpend -= (int)potion.HPvalue; items.Add(potion); // Add potion to random node in dungeon. allNodes[RandomGenerator.rnd.Next(allNodes.Count)].items.Add(potion); } else { break; } } // Generate crystals. for (int i = 0; i < allNodes.Count; i++) { // Each node has 10% chance to spawn a crystal. if (RandomGenerator.rnd.Next(10) == 0) { Crystal crystal = new Crystal("Cry_" + i); items.Add(crystal); // Add crystal to node. allNodes[i].items.Add(crystal); } } }