/// <summary> /// forges alliance between character a and character b families. depending on how the alliance was forged an identifier would be used to determine so /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="x"></param> /// <returns></returns> public static void forgeAlliance(String a, String b) { Character aC = Globals_Game.getCharFromID(a); Character bC = Globals_Game.getCharFromID(b); if (!aC.isAlly(bC) && !bC.isAlly(aC)) { for (int i = 0; i < Globals_Game.npcMasterList.Count; i++) { if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).allies.Add(aC.familyID); } if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).allies.Add(bC.familyID); } } for (int i = 0; i < Globals_Game.pcMasterList.Count; i++) { if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).allies.Add(aC.familyID); } if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).allies.Add(bC.familyID); } } } }
/// <summary> /// Breaks alliance between Character a family and Character b family /// </summary> /// <param name="a"></param> /// <param name="b"></param> public static void removeAlly(String a, String b) { Character aC = Globals_Game.getCharFromID(a); Character bC = Globals_Game.getCharFromID(b); for (int i = 0; i < Globals_Game.npcMasterList.Count; i++) { if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).allies.Remove(aC.familyID); } if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).allies.Remove(bC.familyID); } } for (int i = 0; i < Globals_Game.pcMasterList.Count; i++) { if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).allies.Remove(aC.familyID); } if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).allies.Remove(bC.familyID); } } }
/// <summary> /// Processes functions involved in lodging a new ownership (and kingship) challenge /// Returns ProtoMessage in case of error /// </summary> public ProtoMessage LodgeOwnershipChallenge(PlayerCharacter challenger) { bool proceed = true; ProtoMessage result = null; // ensure aren't current owner if (challenger == this.owner) { result = new ProtoMessage(); result.ResponseType = DisplayMessages.KingdomAlreadyKing; } else { // create and send new OwnershipChallenge OwnershipChallenge newChallenge = new OwnershipChallenge(Globals_Game.GetNextOwnChallengeID(), challenger.charID, "kingdom", this.id); proceed = Globals_Game.AddOwnershipChallenge(newChallenge, out result); } if (proceed) { // create and send journal entry // get interested parties PlayerCharacter currentOwner = this.owner; // ID uint entryID = Globals_Game.GetNextJournalEntryID(); // date uint year = Globals_Game.clock.currentYear; byte season = Globals_Game.clock.currentSeason; // location string entryLoc = this.id; // journal entry personae string allEntry = "all|all"; string currentOwnerEntry = currentOwner.charID + "|king"; string challengerEntry = challenger.charID + "|pretender"; string[] entryPersonae = new string[] { currentOwnerEntry, challengerEntry, allEntry }; // entry type string entryType = "depose_new"; // journal entry description string[] fields = new string[4]; fields[0] = this.name; fields[1] = this.id; fields[2] = challenger.firstName + " " + challenger.familyName; fields[3] = currentOwner.firstName + " " + currentOwner.familyName; ProtoMessage ownershipChallenge = new ProtoMessage(); ownershipChallenge.MessageFields = fields; ownershipChallenge.ResponseType = DisplayMessages.KingdomOwnershipChallenge; // create and send a proposal (journal entry) JournalEntry myEntry = new JournalEntry(entryID, year, season, entryPersonae, entryType, ownershipChallenge, loc: entryLoc); Globals_Game.AddPastEvent(myEntry); } return(result); }
/// <summary> /// Assert that the test client is logged in, has a PlayerCharacter and is a registered observer /// </summary> /// <param name="testClient"></param> /// <param name="client"></param> /// <returns></returns> public bool ValidClientState(TestClient testClient, out Client client) { if (testClient.net == null || !testClient.IsConnectedAndLoggedIn()) { client = null; return(false); } // If do not have a PlayerCharacter, are dead etc, expect to fail Globals_Server.Clients.TryGetValue(testClient.playerID, out client); if (client == null) { Assert.AreEqual(testClient.net.GetConnectionStatusString(), "Disconnected"); return(false); } if (client.myPlayerCharacter == null || !client.myPlayerCharacter.isAlive) { Task <string> ReplyTask = testClient.GetServerMessage(); ReplyTask.Wait(); string reply = ReplyTask.Result; Assert.AreEqual(reply, "You have no valid PlayerCharacter!"); return(false); } if (!Globals_Game.IsObserver(client)) { return(false); } return(true); }
/// <summary> /// Adds all characters from family A and B to each others "At War" lists /// </summary> /// <param name="a"></param> /// <param name="b"></param> public static void declareWar(string a, string b) { Character aC = Globals_Game.getCharFromID(a); Character bC = Globals_Game.getCharFromID(b); for (int i = 0; i < Globals_Game.npcMasterList.Count; i++) { if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).atWar.Add(aC.familyID); } if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).atWar.Add(bC.familyID); } } for (int i = 0; i < Globals_Game.pcMasterList.Count; i++) { if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).atWar.Add(aC.familyID); } if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).atWar.Add(bC.familyID); } } }
/// <summary> /// Removes character A and B families from each other "At War" lists /// </summary> /// <param name="a"></param> /// <param name="b"></param> public static void makePeace(string a, string b) { Character aC = Globals_Game.getCharFromID(a); Character bC = Globals_Game.getCharFromID(b); if (aC.wagingWar(bC) && bC.wagingWar(aC)) { for (int i = 0; i < Globals_Game.npcMasterList.Count; i++) { if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).atWar.Remove(aC.familyID); } if (Globals_Game.npcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.npcMasterList.Values.ElementAt(i).atWar.Remove(bC.familyID); } } for (int i = 0; i < Globals_Game.pcMasterList.Count; i++) { if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(bC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).atWar.Remove(aC.familyID); } if (Globals_Game.pcMasterList.Values.ElementAt(i).familyID.Equals(aC.familyID)) { Globals_Game.pcMasterList.Values.ElementAt(i).atWar.Remove(bC.familyID); } } } }
public Client deserialise() { Client c = new Client(user, pcID); c.myPastEvents = this.myPastEvents; c.myPlayerCharacter = Globals_Game.getCharFromID(pcID) as PlayerCharacter; c.activeChar = Globals_Game.getCharFromID(activeChar); return(c); }
/// <summary> /// Test stub for spy character /// </summary> /// <param name="testClient"></param> /// <param name="charID"></param> /// <param name="targetID"></param> /// <param name="DoSpy"></param> public void SpyCharacterTest(TestClient testClient, string charID, string targetID, bool DoSpy) { bool ownsCharacter = true; Character spy = Globals_Game.getCharFromID(charID); Client client = Globals_Server.Clients[testClient.playerID]; if (spy != null) { ownsCharacter = (spy.GetPlayerCharacter().Equals(client.myPlayerCharacter)); } testClient.SpyOnCharacter(charID, targetID); Task <ProtoMessage> responseTask = testClient.GetReply(); responseTask.Wait(); ProtoMessage response = responseTask.Result; // If don't identify either character, CharacterUnidentified error // If don't own spy, PermissionDenied error // If target is own character, SpyCharacterOwn error // If target is not in same fief as spy, TooFarFromFief error // If target is not valid, other error // Otherwise, expect a response if (string.IsNullOrWhiteSpace(charID) || string.IsNullOrWhiteSpace(targetID)) { Assert.AreEqual(DisplayMessages.ErrorGenericMessageInvalid, response.ResponseType); return; } Character target = Globals_Game.getCharFromID(targetID); if (spy == null || target == null) { Assert.AreEqual(DisplayMessages.ErrorGenericCharacterUnidentified, response.ResponseType); return; } if (!ownsCharacter) { Assert.AreEqual(DisplayMessages.ErrorGenericUnauthorised, response.ResponseType); return; } if (spy.location != target.location) { Assert.AreEqual(DisplayMessages.ErrorGenericNotInSameFief, response.ResponseType); return; } if (spy.days < 10) { Assert.AreEqual(DisplayMessages.ErrorGenericNotEnoughDays, response.ResponseType); return; } if (target.GetPlayerCharacter() == spy.GetPlayerCharacter()) { Assert.AreEqual(DisplayMessages.ErrorSpyOwn, response.ResponseType); return; } }
public void LogInTwiceAsDifferentUsers() { // Tell the client it isn't logged in client.net.loggedIn = false; // Try to log in as anothr user client.LogInAndConnect(OtherUser, OtherPass, new byte[] { 1, 2, 3, 4, 5, 6, 7 }); while (!client.IsConnectedAndLoggedIn()) { Thread.Sleep(0); } Assert.IsFalse(Globals_Game.IsObserver(OtherUser)); }
/// <summary> /// Set up the data and game state for the test run /// </summary> public static void InitialiseGameState() { //game = new Game(); //server = new Server(); //client = new TestClient(); Username = "******"; Pass = "******"; MyPlayerCharacter = Globals_Game.ownedPlayerCharacters[Username]; #if DEBUG // We want to run the test with constants, so we set the success chance to 100 to remove random element MyPlayerCharacter.fixedSuccessChance = 100; #endif Dictionary <string, PlayerCharacter> .Enumerator e = Globals_Game.pcMasterList.GetEnumerator(); e.MoveNext(); NotMyPlayerCharacter = e.Current.Value; while (NotMyPlayerCharacter == MyPlayerCharacter) { e.MoveNext(); NotMyPlayerCharacter = e.Current.Value; } if (MyPlayerCharacter.myArmies != null && MyPlayerCharacter.myArmies.Count > 0) { OwnedArmy = MyPlayerCharacter.myArmies[0]; } else { Army army = new Army(Globals_Game.GetNextArmyID(), null, MyPlayerCharacter.charID, 30, NotMyPlayerCharacter.location.id, false, trp: new uint[] { 5, 5, 5, 5, 5, 5 }); OwnedArmy = army; OwnedArmy.AddArmy(); } if (NotMyPlayerCharacter.myArmies != null && NotMyPlayerCharacter.myArmies.Count > 0) { NotOwnedArmy = NotMyPlayerCharacter.myArmies[0]; } else { Army army = new Army(Globals_Game.GetNextArmyID(), null, NotMyPlayerCharacter.charID, 30, NotMyPlayerCharacter.location.id, false, trp: new uint[] { 5, 5, 5, 5, 5, 5 }); NotOwnedArmy = army; NotOwnedArmy.AddArmy(); } if (MyPlayerCharacter.ownedFiefs != null && MyPlayerCharacter.ownedFiefs.Count > 0) { OwnedFief = MyPlayerCharacter.ownedFiefs[0]; } if (NotMyPlayerCharacter.ownedFiefs != null && NotMyPlayerCharacter.ownedFiefs.Count > 0) { NotOwnedFief = NotMyPlayerCharacter.ownedFiefs[0]; } }
///// <summary> ///// The main entry point for the application. ///// </summary> //static void Main() //{ // try // { // using (Globals_Server.LogFile = new System.IO.StreamWriter("LogFile.txt")) // { // //Globals_Server.rCluster = RiakCluster.FromConfig("riakConfig","app.config"); // //Globals_Server.rClient = Globals_Server.rCluster.CreateClient(); // Globals_Server.LogFile.AutoFlush = true; // Globals_Server.logEvent("Server start"); // Game game = new Game(); // SetUpForDemo(); // /* // //DatabaseWrite.DatabaseWriteAll ("testBucket"); // /*if (Globals_Server.rClient.Ping ().IsSuccess) { // Console.WriteLine ("Database connection successful"); // string gameID = "testBucket"; // foreach (string trait in Globals_Game.traitKeys) { // Console.WriteLine (trait); // } // // Test can read from database // var newClient = Globals_Server.rCluster.CreateClient(); // RiakObject newObj = new RiakObject (gameID, "superawesome3", Globals_Game.traitKeys.ToArray ()); // newClient.Put (newObj); // Thread.Sleep (5000); // var testRead =newClient.Get (gameID, "superawesome3"); // if (!testRead.IsSuccess) { // Console.WriteLine ("FAIL :(" + testRead.ErrorMessage); // } else { // Console.WriteLine ("Got traitkeys:"); // } // //DatabaseRead.DatabaseReadAll (gameID); // } else { // Console.WriteLine ("Could not connect to database :( "); // } */ // //testCaptives(); // Server server = new Server(); // try // { // //TestSuite testSuite = new TestSuite(); // TestClient client = new TestClient(); // client.LogInAndConnect("helen", "potato"); // } // catch (Exception e) // { // Console.WriteLine(e.Message); // } // //client.LogIn("helen", "potato"); // String s = Console.ReadLine(); // if (s != null && s.Equals("exit")) // { // Globals_Server.logEvent("Server exits"); // server.isListening = false; // Globals_Server.server.Shutdown("Server exits"); // } // //testArmy(); // //testSpying(); // /* // while (true) // { // if (s != null && s.Equals("exit")) // { // Globals_Server.logEvent("Server exits"); // server.isListening = false; // Globals_Server.server.Shutdown("Server exits"); // break; // } // } // * */ // Globals_Server.LogFile.Close(); // } // } // catch (Exception e) // { // Globals_Server.LogFile.Close(); // Console.WriteLine("Encountered an error:" + e.StackTrace); // Console.ReadLine(); // } //} /// <summary> /// Code which was used in the 2015 demo- sets up a few armies, adds funds and sets a few traits to demonstrate trait effects /// </summary> public static void SetUpForDemo() { // Make Anselm Marshal very sneaky Character Anselm = Globals_Game.getCharFromID("Char_390"); Character Bishop = Globals_Game.getCharFromID("Char_391"); Tuple <Trait, int>[] newTraits = new Tuple <Trait, int> [2]; newTraits[0] = new Tuple <Trait, int>(Globals_Game.traitMasterList["trait_9"], 9); newTraits[1] = new Tuple <Trait, int>(Globals_Game.traitMasterList["trait_8"], 9); Anselm.traits = newTraits; // Make Bishop Henry Marshal not sneaky Tuple <Trait, int>[] newTraits2 = new Tuple <Trait, int> [1]; newTraits2[0] = new Tuple <Trait, int>(Globals_Game.traitMasterList["trait_5"], 2); Bishop.traits = newTraits2; // Add funds to home treasury (Globals_Game.getCharFromID("Char_158") as PlayerCharacter).GetHomeFief().AdjustTreasury(100000); // create enemy character in home fief NonPlayerCharacter enemyGeneral = new NonPlayerCharacter("Char_164459", "John", "Smith", new Tuple <uint, byte>(1142, 3), true, Globals_Game.nationalityMasterList["Sco"], true, 9, 9, new Queue <Fief>(), Globals_Game.languageMasterList["lang_C1"], 90, 9, 9, 9, new Tuple <Trait, int> [0], true, false, "Char_126", null, "Char_126", null, 0, false, false, new List <string>(), null, null, Globals_Game.fiefMasterList["EPM02"]); PlayerCharacter factionLeader = Globals_Game.pcMasterList["Char_126"]; factionLeader.myNPCs.Add(enemyGeneral); enemyGeneral.inKeep = false; // create enemy army for above enemy character uint[] enemyArmyTroops = new uint[] { 3, 7, 0, 20, 30, 65, 190 }; Army enemyArmy = new Army(Globals_Game.GetNextArmyID(), Globals_Game.npcMasterList["Char_164459"].charID, Globals_Game.pcMasterList["Char_196"].charID, Globals_Game.npcMasterList["Char_164459"].days, Globals_Game.npcMasterList["Char_164459"].location.id, trp: enemyArmyTroops); enemyArmy.AddArmy(); // create and add army uint[] myArmyTroops1 = new uint[] { 8, 10, 0, 30, 60, 100, 220 }; Army myArmy1 = new Army(Globals_Game.GetNextArmyID(), Globals_Game.pcMasterList["Char_196"].charID, Globals_Game.pcMasterList["Char_196"].charID, Globals_Game.pcMasterList["Char_196"].days, Globals_Game.pcMasterList["Char_196"].location.id, trp: myArmyTroops1); myArmy1.AddArmy(); // create and add army uint[] myArmyTroops2 = new uint[] { 5, 10, 0, 30, 40, 80, 220 }; Army myArmy2 = new Army(Globals_Game.GetNextArmyID(), Globals_Game.pcMasterList["Char_158"].charID, Globals_Game.pcMasterList["Char_158"].charID, Globals_Game.pcMasterList["Char_158"].days, Globals_Game.pcMasterList["Char_158"].location.id, trp: myArmyTroops2, aggr: 1, odds: 2); myArmy2.AddArmy(); // Add single lady appropriate for marriage //Nationality nat = Globals_Game.nationalityMasterList["Sco"]; NonPlayerCharacter proposalChar = new NonPlayerCharacter("Char_626", "Mairi", "Meah", new Tuple <uint, byte>(1162, 3), false, Globals_Game.nationalityMasterList["Sco"], true, 9, 9, new Queue <Fief>(), Globals_Game.languageMasterList["lang_C1"], 90, 9, 9, 9, new Tuple <Trait, int> [0], true, false, "Char_126", null, "Char_126", null, 0, false, false, new List <string>(), null, null, Globals_Game.fiefMasterList["ESW05"]); PlayerCharacter pc = Globals_Game.pcMasterList["Char_126"]; pc.myNPCs.Add(proposalChar); proposalChar.inKeep = false; }
/// <summary>Test stub for LogIn(String, String, Byte[])</summary> public void LogInTest( TestClient client, string user, string pass, byte[] key ) { client.LogInAndConnect(user, pass, key); // If username not recognised, expect to be disconnected if (string.IsNullOrEmpty(user) || !Utility_Methods.CheckStringValid("combined", user) || !LogInManager.users.ContainsKey(user)) { Assert.AreEqual("Disconnected", client.net.GetConnectionStatusString()); return; } // If password is incorrect, expect an error Tuple <byte[], byte[]> hashNsalt = LogInManager.users[user]; byte[] hash; if (pass == null) { hash = null; } else { hash = LogInManager.ComputeHash(System.Text.Encoding.UTF8.GetBytes(pass), hashNsalt.Item2); } if (hash == null || !hashNsalt.Item1.SequenceEqual(hash) || key == null || key.Length < 5) { Assert.AreEqual("Disconnected", client.net.GetConnectionStatusString()); Assert.IsFalse(Server.ContainsConnection(user)); } else { // If the login was successful, expecting a ProtoLogin followed by a ProtoClient back Task <ProtoMessage> getReply = client.GetReply(); getReply.Wait(); ProtoMessage reply = getReply.Result; Assert.AreEqual(reply.GetType(), typeof(ProtoLogIn)); while (!client.IsConnectedAndLoggedIn()) { Thread.Sleep(0); } // If login was successful, the client should be in the list of registered observers Assert.IsTrue(Globals_Game.IsObserver(Globals_Server.Clients[user])); Assert.IsTrue(Server.ContainsConnection(user)); } }
/// <summary> /// Test stub for spy character /// </summary> /// <param name="testClient"></param> /// <param name="charID"></param> /// <param name="targetID"></param> /// <param name="DoSpy"></param> public void SpyFiefTest(TestClient testClient, string charID, string targetID, bool DoSpy) { Character spy = Globals_Game.getCharFromID(charID); Client client = Globals_Server.Clients[testClient.playerID]; bool ownSpy = true; if (spy != null) { ownSpy = (spy.GetPlayerCharacter().Equals(client.myPlayerCharacter)); } testClient.SpyOnFief(charID, targetID); Task <ProtoMessage> responseTask = testClient.GetReply(); responseTask.Wait(); ProtoMessage response = responseTask.Result; if (string.IsNullOrWhiteSpace(charID) || string.IsNullOrWhiteSpace(targetID)) { Assert.AreEqual(DisplayMessages.ErrorGenericMessageInvalid, response.ResponseType); return; } Fief target = null; Globals_Game.fiefMasterList.TryGetValue(targetID, out target); if (spy == null || target == null) { Assert.AreEqual(DisplayMessages.ErrorGenericCharacterUnidentified, response.ResponseType); return; } if (!ownSpy) { Assert.AreEqual(DisplayMessages.ErrorGenericUnauthorised, response.ResponseType); return; } if (spy.location != target) { Assert.AreEqual(DisplayMessages.ErrorGenericNotInSameFief, response.ResponseType); return; } if (spy.days < 10) { Assert.AreEqual(DisplayMessages.ErrorGenericNotEnoughDays, response.ResponseType); return; } }
/// <summary> /// Processes a client disconnecting from the server- removes the client as an observer, removes their connection and deletes their CryptoServiceProvider /// </summary> /// <param name="conn">Connection of the client who disconnected</param> private void Disconnect(NetConnection conn) { Contract.Requires(conn != null); lock (ServerLock) { if (clientConnections.ContainsKey(conn)) { Client client = clientConnections[conn]; Globals_Server.logEvent("Client " + client.username + " disconnects"); Globals_Game.RemoveObserver(client); client.conn = null; clientConnections.Remove(conn); client.alg = null; conn.Disconnect("Disconnect"); } } }
public static bool ProcessLogIn(global::ProtoMessage.ProtoLogIn login, global::ProtoMessage.Client c, bool isPCL) { Contract.Requires(c != null && login != null); if (!VerifyUser(c.username, login.userSalt)) { return(false); } try { if (login.Key != null) { byte[] key = rsa.Decrypt(login.Key, false); // Key must be non-null and long enough if (key == null || key.Length < 5) { return(false); } c.alg = new NetAESEncryption(Globals_Server.server, key, 0, key.Length); } else { #if ALLOW_UNENCRYPT c.alg = null; #else return(false); #endif } global::ProtoMessage.ProtoClient clientDetails = new global::ProtoMessage.ProtoClient(c); clientDetails.ActionType = global::ProtoMessage.Actions.LogIn; clientDetails.ResponseType = global::ProtoMessage.DisplayMessages.LogInSuccess; Server.SendViaProto(clientDetails, c.conn, true, c.alg); Globals_Game.RegisterObserver(c); return(true); } catch (Exception e) { #if DEBUG Console.WriteLine("Failure during decryption: " + e.GetType() + " " + e.Message + ";" + e.StackTrace); #endif return(false); } }
/// <summary> /// Test stub for spy character /// </summary> /// <param name="testClient"></param> /// <param name="charID"></param> /// <param name="targetID"></param> /// <param name="DoSpy"></param> public void SpyArmyTest(TestClient testClient, string charID, string targetID) { testClient.SpyOnArmy(charID, targetID); Task <ProtoMessage> responseTask = testClient.GetReply(); responseTask.Wait(); ProtoMessage response = responseTask.Result; if (string.IsNullOrWhiteSpace(charID) || string.IsNullOrWhiteSpace(targetID)) { Assert.AreEqual(DisplayMessages.ErrorGenericMessageInvalid, response.ResponseType); return; } Character spy = Globals_Game.getCharFromID(charID); Army target = null; Globals_Game.armyMasterList.TryGetValue(targetID, out target); if (spy == null || target == null) { Assert.AreEqual(DisplayMessages.ErrorGenericCharacterUnidentified, response.ResponseType); return; } Client client = Globals_Server.Clients[testClient.playerID]; if (spy.GetPlayerCharacter() != client.myPlayerCharacter) { Assert.AreEqual(DisplayMessages.ErrorGenericUnauthorised, response.ResponseType); return; } if (spy.location != target.GetLocation()) { Assert.AreEqual(DisplayMessages.ErrorGenericNotInSameFief, response.ResponseType); return; } if (!(spy.days >= 10)) { Assert.AreEqual(DisplayMessages.ErrorGenericNotEnoughDays, response.ResponseType); return; } }
/// <summary> /// Creates a JournalEntry for the attention of the game sysAdmin /// </summary> /// <returns>random double</returns> public static JournalEntry CreateSysAdminJentry() { JournalEntry jEntry = null; if (Globals_Game.sysAdmin != null) { // ID uint jEntryID = Globals_Game.GetNextJournalEntryID(); // date uint year = Globals_Game.clock.currentYear; byte season = Globals_Game.clock.currentSeason; // personae string sysAdminEntry = Globals_Game.sysAdmin.charID + "|sysAdmin"; string[] jEntryPersonae = new string[] { sysAdminEntry }; // create and send a proposal (journal entry) ProtoMessage errorMessage = new ProtoMessage(); jEntry = new JournalEntry(jEntryID, year, season, jEntryPersonae, "CSV_importError", errorMessage); } return(jEntry); }
public void Listen() { while (server.Status == NetPeerStatus.Running && !ctSource.Token.IsCancellationRequested) { NetIncomingMessage im; WaitHandle.WaitAny(new WaitHandle[] { server.MessageReceivedEvent, ctSource.Token.WaitHandle }); while ((im = server.ReadMessage()) != null && !ctSource.Token.IsCancellationRequested) { if (im.SenderConnection != null) { Globals_Server.logEvent("Recieved: " + im.MessageType.ToString() + " | " + im.SenderConnection.RemoteEndPoint.ToString()); } else { Globals_Server.logEvent("Recieved: " + im.MessageType.ToString() + " | NULL"); } switch (im.MessageType) { case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.ErrorMessage: case NetIncomingMessageType.WarningMessage: Globals_Server.logError("Recieved warning message: " + im.ReadString()); break; case NetIncomingMessageType.VerboseDebugMessage: case NetIncomingMessageType.Data: { #if DEBUG //Console.WriteLine("SERVER: recieved data message"); #endif if (!clientConnections.ContainsKey(im.SenderConnection)) { //error im.SenderConnection.Disconnect("Not recognised"); return; } Client c = clientConnections[im.SenderConnection]; if (c.alg != null) { im.Decrypt(c.alg); } ProtoMessage m = null; using (MemoryStream ms = new MemoryStream(im.Data)) { try { m = Serializer.DeserializeWithLengthPrefix <ProtoMessage>(ms, PrefixStyle.Fixed32); } catch (Exception e) { NetOutgoingMessage errorMessage = server.CreateMessage( "Failed to deserialise message. The message may be incorrect, or the decryption may have failed."); if (c.alg != null) { errorMessage.Encrypt(c.alg); } server.SendMessage(errorMessage, im.SenderConnection, NetDeliveryMethod.ReliableOrdered); Globals_Server.logError("Failed to deserialize message for client: " + c.username); } } if (m == null) { string error = "Recieved null message from " + im.SenderEndPoint.ToString(); if (clientConnections.ContainsKey(im.SenderConnection)) { error += ", recognised client " + clientConnections[im.SenderConnection]; } else { error += ", unrecognised client (possible ping)"; } error += ". Data: " + im.ReadString(); Globals_Server.logError(error); break; } if (m.ActionType == Actions.LogIn) { ProtoLogIn login = m as ProtoLogIn; if (login == null) { im.SenderConnection.Disconnect("Received blank login message."); return; } lock (ServerLock) { if (LogInManager.VerifyUser(c.username, login.userSalt)) { if (LogInManager.ProcessLogIn(login, c)) { string log = c.username + " logs in from " + im.SenderEndPoint.ToString(); Globals_Server.logEvent(log); } } else { ProtoMessage reply = new ProtoMessage { ActionType = Actions.LogIn, ResponseType = DisplayMessages.LogInFail }; Server.SendViaProto(reply, c.conn, c.alg); //reply = new ProtoMessage { // ActionType = Actions.Update, // ResponseType = DisplayMessages.Error //}; //Server.SendViaProto(reply, c.conn, c.alg); im.SenderConnection.Disconnect("Authentication Fail"); Globals_Server.logEvent("Wrong Password, disconnecting user."); } } } // temp for testing, should validate connection first else if (clientConnections.ContainsKey(im.SenderConnection)) { if (Globals_Game.IsObserver(c)) { ProcessMessage(m, im.SenderConnection); ProtoClient clientDetails = new ProtoClient(c); clientDetails.ActionType = Actions.Update; clientDetails.ResponseType = DisplayMessages.Success; SendViaProto(clientDetails, im.SenderConnection, c.alg); } else { im.SenderConnection.Disconnect("Not logged in- Disconnecting"); } } } break; case NetIncomingMessageType.StatusChanged: byte stat = im.ReadByte(); NetConnectionStatus status = NetConnectionStatus.None; if (Enum.IsDefined(typeof(NetConnectionStatus), Convert.ToInt32(stat))) { status = (NetConnectionStatus)stat; } else { Globals_Server.logError("Failure to parse byte " + stat + " to NetConnectionStatus for endpoint " + im.ReadIPEndPoint()); } Globals_Server.logEvent("\tStatus is now: " + status); if (status == NetConnectionStatus.Disconnected) { string reason = im.ReadString(); if (reason == null) { reason = "Unknown"; } Globals_Server.logEvent(im.SenderConnection.RemoteEndPoint.ToString() + " has disconnected. Reason: " + reason); if (clientConnections.ContainsKey(im.SenderConnection)) { Disconnect(im.SenderConnection); } } break; case NetIncomingMessageType.ConnectionApproval: { string senderID = im.ReadString(); string text = im.ReadString(); Client client; Globals_Server.Clients.TryGetValue(senderID, out client); if (client != null) { ProtoLogIn logIn; //ProtoMessage logIn; if (!LogInManager.AcceptConnection(client, text, out logIn)) { im.SenderConnection.Deny("User not recognised."); } else { ProtoMessage temp = logIn; NetOutgoingMessage msg = server.CreateMessage(); MemoryStream ms = new MemoryStream(); // Include X509 certificate as bytes for client to validate //Serializer.SerializeWithLengthPrefix<ProtoLogIn>(ms, logIn, PrefixStyle.Fixed32); Serializer.SerializeWithLengthPrefix <ProtoMessage>(ms, temp, PrefixStyle.Fixed32); msg.Write(ms.GetBuffer()); clientConnections.Add(im.SenderConnection, client); client.conn = im.SenderConnection; im.SenderConnection.Approve(msg); //server.FlushSendQueue(); Globals_Server.logEvent("Accepted connection from " + client.username + " | " + senderID + " | " + text); } } else { im.SenderConnection.Deny("Username unrecognised."); } server.FlushSendQueue(); } break; case NetIncomingMessageType.ConnectionLatencyUpdated: Globals_Server.logEvent("LATENCY: Still getting these."); break; default: Globals_Server.logError("Received unrecognised incoming message type: " + im.MessageType); break; } server.Recycle(im); } } Globals_Server.logEvent("Server listening thread exits."); }
/// <summary> /// Calculates the outcome of the pillage of a fief by an army /// </summary> /// <param name="f">The fief being pillaged</param> /// <param name="a">The pillaging army</param> /// <param name="circumstance">The circumstance under which the fief is being pillaged</param> public static ProtoPillageResult ProcessPillage(Fief f, Army a, string circumstance = "pillage") { ProtoPillageResult pillageResult = new ProtoPillageResult(); double thisLoss = 0; double moneyPillagedTotal = 0; double moneyPillagedOwner = 0; double pillageMultiplier = 0; // get army leader Character armyLeader = a.GetLeader(); // get pillaging army owner (receives a proportion of total spoils) PlayerCharacter armyOwner = a.GetOwner(); pillageResult.fiefID = f.id; // get garrison leader (to add to journal entry) Character defenderLeader = null; if (f.bailiff != null) { defenderLeader = f.bailiff; } // calculate pillageMultiplier (based on no. pillagers per 1000 population) pillageMultiplier = a.CalcArmySize() / (f.population / 1000); // calculate days taken for pillage double daysTaken = Globals_Game.myRand.Next(7, 16); if (daysTaken > a.days) { daysTaken = a.days; } // update army days armyLeader.AdjustDays(daysTaken); pillageResult.daysTaken = daysTaken; // % population loss thisLoss = (0.007 * pillageMultiplier); // ensure is between 1%-20% if (thisLoss < 1) { thisLoss = 1; } else if (thisLoss > 20) { thisLoss = 20; } // apply population loss pillageResult.populationLoss = Convert.ToInt32((f.population * (thisLoss / 100))); f.population -= Convert.ToInt32((f.population * (thisLoss / 100))); // % treasury loss if (!circumstance.Equals("quellRebellion")) { thisLoss = (0.2 * pillageMultiplier); // ensure is between 1%-80% if (thisLoss < 1) { thisLoss = 1; } else if (thisLoss > 80) { thisLoss = 80; } // apply treasury loss if (f.Treasury > 0) { pillageResult.treasuryLoss = Convert.ToInt32((f.Treasury * (thisLoss / 100))); f.AdjustTreasury(-Convert.ToInt32((f.Treasury * (thisLoss / 100)))); } } // % loyalty loss thisLoss = (0.33 * pillageMultiplier); // ensure is between 1%-20% if (thisLoss < 1) { thisLoss = 1; } else if (thisLoss > 20) { thisLoss = 20; } // apply loyalty loss pillageResult.loyaltyLoss = (f.loyalty * (thisLoss / 100)); f.loyalty -= (f.loyalty * (thisLoss / 100)); // % fields loss thisLoss = (0.01 * pillageMultiplier); // ensure is between 1%-20% if (thisLoss < 1) { thisLoss = 1; } else if (thisLoss > 20) { thisLoss = 20; } // apply fields loss pillageResult.fieldsLoss = (f.fields * (thisLoss / 100)); f.fields -= (f.fields * (thisLoss / 100)); // % industry loss thisLoss = (0.01 * pillageMultiplier); // ensure is between 1%-20% if (thisLoss < 1) { thisLoss = 1; } else if (thisLoss > 20) { thisLoss = 20; } // apply industry loss pillageResult.industryLoss = (f.industry * (thisLoss / Convert.ToDouble(100))); f.industry -= (f.industry * (thisLoss / 100)); // money pillaged (based on GDP) thisLoss = (0.032 * pillageMultiplier); // ensure is between 1%-50% if (thisLoss < 1) { thisLoss = 1; } else if (thisLoss > 50) { thisLoss = 50; } // calculate base amount pillaged based on fief GDP double baseMoneyPillaged = (f.keyStatsCurrent[1] * (thisLoss / 100)); moneyPillagedTotal = baseMoneyPillaged; pillageResult.baseMoneyPillaged = baseMoneyPillaged; // factor in no. days spent pillaging (get extra 5% per day > 7) int daysOver7 = Convert.ToInt32(daysTaken) - 7; if (daysOver7 > 0) { for (int i = 0; i < daysOver7; i++) { moneyPillagedTotal += (baseMoneyPillaged * 0.05); } pillageResult.bonusMoneyPillaged = moneyPillagedTotal - baseMoneyPillaged; pillageResult.daysTaken = daysOver7; } // check for jackpot // generate randomPercentage to see if hit the jackpot int myRandomPercent = Globals_Game.myRand.Next(101); if (myRandomPercent <= 30) { // generate random int to multiply amount pillaged int myRandomMultiplier = Globals_Game.myRand.Next(3, 11); pillageResult.jackpot = moneyPillagedTotal * myRandomMultiplier - moneyPillagedTotal; moneyPillagedTotal = moneyPillagedTotal * myRandomMultiplier; } // check proportion of money pillaged goes to army owner (based on stature) double proportionForOwner = 0.05 * armyOwner.CalculateStature(); moneyPillagedOwner = (moneyPillagedTotal * proportionForOwner); pillageResult.moneyPillagedOwner = moneyPillagedOwner; // apply to army owner's home fief treasury armyOwner.GetHomeFief().AdjustTreasury(Convert.ToInt32(moneyPillagedOwner)); // apply loss of stature to army owner if fief has same language if (armyOwner.language.id == f.language.id) { armyOwner.AdjustStatureModifier(-0.3); pillageResult.statureModifier = (-0.3); } else if (armyOwner.language.baseLanguage.id == f.language.baseLanguage.id) { armyOwner.AdjustStatureModifier(-0.2); pillageResult.statureModifier = (-0.2); } // set isPillaged for fief f.isPillaged = true; // =================== construct and send JOURNAL ENTRY // ID uint entryID = Globals_Game.GetNextJournalEntryID(); // personae List <string> tempPersonae = new List <string>(); tempPersonae.Add(f.owner.charID + "|fiefOwner"); tempPersonae.Add(armyOwner.charID + "|attackerOwner"); if (armyLeader != null) { tempPersonae.Add(armyLeader.charID + "|attackerLeader"); } if ((defenderLeader != null) && (!circumstance.Equals("quellRebellion"))) { tempPersonae.Add(defenderLeader.charID + "|defenderLeader"); } if (circumstance.Equals("quellRebellion")) { tempPersonae.Add("all|all"); } string[] pillagePersonae = tempPersonae.ToArray(); // location string pillageLocation = f.id; // type string type = ""; if (circumstance.Equals("pillage")) { type += "pillage"; } else if (circumstance.Equals("quellRebellion")) { type += "rebellionQuelled"; } if (circumstance.Equals("pillage")) { pillageResult.isPillage = true; } else if (circumstance.Equals("quellRebellion")) { pillageResult.isPillage = false; } pillageResult.fiefName = f.name; pillageResult.fiefOwner = f.owner.firstName + " " + f.owner.familyName; if ((circumstance.Equals("pillage")) && (defenderLeader != null)) { if (f.owner != defenderLeader) { pillageResult.defenderLeader = defenderLeader.firstName + " " + defenderLeader.familyName; } } pillageResult.armyOwner = armyOwner.firstName + " " + armyOwner.familyName; if (armyLeader != null) { pillageResult.armyLeader = armyLeader.firstName + " " + armyLeader.familyName; } // put together new journal entry JournalEntry pillageEntry = new JournalEntry(pillageResult, entryID, Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, pillagePersonae, type, loc: pillageLocation); // add new journal entry to pastEvents Globals_Game.AddPastEvent(pillageEntry); return(pillageResult); }
/// <summary> /// Respond to ransom demands /// </summary> /// <param name="paid">Whether or not ransom is to be paid</param> /// <returns>Bool indicating success</returns> public bool RansomResponse(bool paid, out ProtoMessage error) { error = null; // Check if type is ransom if (this.type.Equals("ransom")) { // Check if already replied if (replied) { // Already replied error = new ProtoMessage(); error.ResponseType = DisplayMessages.RansomRepliedAlready; return(false); } Character captive = null; PlayerCharacter captor; PlayerCharacter captiveHeadOfHousehold; // Confirm captive is still alive and being held foreach (string persona in personae) { string[] split = persona.Split(new char[] { '|' }); if (split[1].Equals("Captive")) { captive = Globals_Game.getCharFromID(split[0]); } } if (captive == null) { // Captive does not exist- error error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericCharacterUnidentified; Globals_Server.logError("Captive unidentified in JEntry: " + this.jEntryID); return(false); } else if (!captive.isAlive) { // Captive is dead error = new ProtoMessage(); error.ResponseType = DisplayMessages.RansomCaptiveDead; return(false); } captor = Globals_Game.getCharFromID(captive.captorID) as PlayerCharacter; if (captor == null) { // Captive does not have a captor error = new ProtoMessage(); error.ResponseType = DisplayMessages.NotCaptive; return(false); } captiveHeadOfHousehold = captive.GetPlayerCharacter(); if (captiveHeadOfHousehold == null) { // Captive is not an employee, family member or player character Globals_Server.logError("Captive has no PlayerCharacter: " + captive.charID); error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericCharacterUnidentified; return(false); } if (paid) { // Get ransom amount uint ransom = 0; if (!UInt32.TryParse(entryDetails.MessageFields[1], out ransom)) { // Error parsing to int Globals_Server.logError("Could not parse ransom to uint in JEntry: " + jEntryID); error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericMessageInvalid; return(false); } else { // Check captive's head of household has the funds to release if (captiveHeadOfHousehold.GetHomeFief().GetAvailableTreasury(false) >= ransom) { if (!captiveHeadOfHousehold.GetHomeFief().TreasuryTransfer(captor.GetHomeFief(), (Int32)ransom, out error)) { return(false); } else { // Release captive captor.ReleaseCaptive(captive); replied = true; Globals_Game.UpdatePlayer(captor.playerID, DisplayMessages.RansomPaid, new string[] { captive.firstName + " " + captive.familyName }); return(true); } } else { // Insufficient funds error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericInsufficientFunds; return(false); } } } // If not paying ransom, inform captor else { // Create journal entry and update captor string[] newPersonae = new string[] { captive.charID + "|Captive", captor.charID + "|Captor", captiveHeadOfHousehold.charID + "|HeadOfCaptiveFamily" }; ProtoMessage deniedMessage = new ProtoMessage(); deniedMessage.ResponseType = DisplayMessages.RansonDenied; deniedMessage.MessageFields = new string[] { captive.firstName + " " + captive.familyName, captor.firstName + " " + captor.familyName, captiveHeadOfHousehold.firstName + " " + captiveHeadOfHousehold.familyName }; Globals_Game.UpdatePlayer(captor.playerID, deniedMessage); JournalEntry ransomDenied = new JournalEntry(Globals_Game.GetNextJournalEntryID(), Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, newPersonae, "ransomDenied", deniedMessage); Globals_Game.AddPastEvent(ransomDenied); replied = true; return(true); } } else { // Not a ransom error = new ProtoMessage(); error.ResponseType = DisplayMessages.EntryNotRansom; return(false); } }
public static void InitialiseGameState(TestContext ctx = null) { Globals_Server.LogFile = new System.IO.StreamWriter("LogFile.txt"); Globals_Server.LogFile.AutoFlush = true; game = new Game(); server = new Server(); client = new TestClient(); Username = "******"; Pass = "******"; OtherUser = "******"; OtherPass = "******"; BadUsername = "******"; BadPass = "******"; MyPlayerCharacter = Globals_Game.ownedPlayerCharacters[Username]; Dictionary <string, PlayerCharacter> .Enumerator e = Globals_Game.pcMasterList.GetEnumerator(); e.MoveNext(); NotMyPlayerCharacter = e.Current.Value; while (NotMyPlayerCharacter == MyPlayerCharacter) { e.MoveNext(); NotMyPlayerCharacter = e.Current.Value; } foreach (NonPlayerCharacter npc in MyPlayerCharacter.myNPCs) { if (!string.IsNullOrWhiteSpace(npc.familyID)) { MyFamily = npc; } else if (!string.IsNullOrWhiteSpace(npc.employer)) { MyEmployee = npc; } if (MyEmployee != null && MyFamily != null) { break; } } foreach (NonPlayerCharacter npc in NotMyPlayerCharacter.myNPCs) { if (!string.IsNullOrWhiteSpace(npc.familyID)) { NotMyFamily = npc; } else if (!string.IsNullOrWhiteSpace(npc.employer)) { NotMyEmplployee = npc; } if (NotMyEmplployee != null && NotMyFamily != null) { break; } } if (MyPlayerCharacter.myArmies != null && MyPlayerCharacter.myArmies.Count > 0) { OwnedArmy = MyPlayerCharacter.myArmies[0]; } else { Army army = new Army(Globals_Game.GetNextArmyID(), null, MyPlayerCharacter.charID, 30, NotMyPlayerCharacter.location.id, false, trp: new uint[] { 5, 5, 5, 5, 5, 5, 5 }); OwnedArmy = army; OwnedArmy.AddArmy(); } if (NotMyPlayerCharacter.myArmies != null && NotMyPlayerCharacter.myArmies.Count > 0) { NotOwnedArmy = NotMyPlayerCharacter.myArmies[0]; } else { Army army = new Army(Globals_Game.GetNextArmyID(), null, NotMyPlayerCharacter.charID, 30, NotMyPlayerCharacter.location.id, false, trp: new uint[] { 5, 5, 5, 5, 5, 5, 5 }); NotOwnedArmy = army; NotOwnedArmy.AddArmy(); } if (MyPlayerCharacter.ownedFiefs != null && MyPlayerCharacter.ownedFiefs.Count > 0) { OwnedFief = MyPlayerCharacter.ownedFiefs[0]; } if (NotMyPlayerCharacter.ownedFiefs != null && NotMyPlayerCharacter.ownedFiefs.Count > 0) { NotOwnedFief = NotMyPlayerCharacter.ownedFiefs[0]; } foreach (var npc in Globals_Game.npcMasterList) { if (npc.Value.GetPlayerCharacter() == null) { NobodysCharacter = npc.Value; } } client.LogInAndConnect(Username, Pass, new byte[] { 1, 2, 3, 4, 5, 6 }); while (!client.IsConnectedAndLoggedIn()) { Thread.Sleep(0); } client.ClearMessageQueues(); }
/// <summary> /// Processes the actions involved with an engagement /// </summary> /// <returns>bool indicating whether engagement was processed successfully</returns> public bool ProcessEngagement() { bool success = false; // get interested parties PlayerCharacter headOfFamilyBride = null; PlayerCharacter headOfFamilyGroom = null; Character bride = null; Character groom = null; for (int i = 0; i < this.personae.Length; i++) { string thisPersonae = this.personae[i]; string[] thisPersonaeSplit = thisPersonae.Split('|'); switch (thisPersonaeSplit[1]) { case "headOfFamilyBride": headOfFamilyBride = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; break; case "headOfFamilyGroom": headOfFamilyGroom = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; break; case "bride": bride = Globals_Game.npcMasterList[thisPersonaeSplit[0]]; break; case "groom": if (Globals_Game.pcMasterList.ContainsKey(thisPersonaeSplit[0])) { groom = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; } else if (Globals_Game.npcMasterList.ContainsKey(thisPersonaeSplit[0])) { groom = Globals_Game.npcMasterList[thisPersonaeSplit[0]]; } break; default: break; } } // ID uint replyID = Globals_Game.GetNextJournalEntryID(); // date uint year = Globals_Game.clock.currentYear; byte season = Globals_Game.clock.currentSeason; if (season == 3) { season = 0; year++; } else { season++; } // personae string headOfFamilyBrideEntry = headOfFamilyBride.charID + "|headOfFamilyBride"; string headOfFamilyGroomEntry = headOfFamilyGroom.charID + "|headOfFamilyGroom"; string thisBrideEntry = bride.charID + "|bride"; string thisGroomEntry = groom.charID + "|groom"; string[] marriagePersonae = new string[] { headOfFamilyGroomEntry, headOfFamilyBrideEntry, thisBrideEntry, thisGroomEntry }; // type string type = "marriage"; // create and add a marriage entry to the scheduledEvents journal JournalEntry marriageEntry = new JournalEntry(replyID, year, season, marriagePersonae, type, null); success = Globals_Game.AddScheduledEvent(marriageEntry); // show bride and groom as engaged if (success) { bride.fiancee = groom.charID; groom.fiancee = bride.charID; } return(success); }
// TODO I suspect there may be issues with this if any of the characters die. Test. /// <summary> /// Allows a character to reply to a marriage proposal /// </summary> /// <returns>bool indicating whether reply was processed successfully</returns> /// <param name="proposalAccepted">bool indicating whether proposal accepted</param> public bool ReplyToProposal(bool proposalAccepted) { bool success = true; string[] replyFields = new string[4]; // get interested parties PlayerCharacter headOfFamilyBride = null; PlayerCharacter headOfFamilyGroom = null; Character bride = null; Character groom = null; for (int i = 0; i < this.personae.Length; i++) { string thisPersonae = this.personae[i]; string[] thisPersonaeSplit = thisPersonae.Split('|'); switch (thisPersonaeSplit[1]) { case "headOfFamilyBride": headOfFamilyBride = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; break; case "headOfFamilyGroom": headOfFamilyGroom = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; break; case "bride": bride = Globals_Game.npcMasterList[thisPersonaeSplit[0]]; break; case "groom": if (Globals_Game.pcMasterList.ContainsKey(thisPersonaeSplit[0])) { groom = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; } else if (Globals_Game.npcMasterList.ContainsKey(thisPersonaeSplit[0])) { groom = Globals_Game.npcMasterList[thisPersonaeSplit[0]]; } break; default: break; } } // ID uint replyID = Globals_Game.GetNextJournalEntryID(); // date uint year = Globals_Game.clock.currentYear; byte season = Globals_Game.clock.currentSeason; // personae List <string> tempPersonae = new List <string>(); tempPersonae.Add(headOfFamilyBride.charID + "|headOfFamilyBride"); tempPersonae.Add(headOfFamilyGroom.charID + "|headOfFamilyGroom"); tempPersonae.Add(bride.charID + "|bride"); tempPersonae.Add(groom.charID + "|groom"); if (proposalAccepted) { tempPersonae.Add("all|all"); } string[] myReplyPersonae = tempPersonae.ToArray(); // type string type = ""; if (proposalAccepted) { type = "proposalAccepted"; } else { type = "proposalRejected"; } // description replyFields[0] = groom.firstName + " " + groom.familyName; replyFields[1] = bride.firstName + " " + bride.familyName; if (proposalAccepted) { replyFields[2] = "ACCEPTED"; } else { replyFields[2] = "REJECTED"; } replyFields[3] = headOfFamilyBride.firstName + " " + headOfFamilyBride.familyName; ProtoMessage proposalReply = new ProtoMessage(); proposalReply.MessageFields = replyFields; proposalReply.ResponseType = DisplayMessages.JournalProposalReply; // create and send a proposal reply (journal entry) JournalEntry myProposalReply = new JournalEntry(replyID, year, season, myReplyPersonae, type, proposalReply, null); success = Globals_Game.AddPastEvent(myProposalReply); if (success) { string[] newFields = new string[this.entryDetails.MessageFields.Length + 2]; Array.Copy(this.entryDetails.MessageFields, newFields, this.entryDetails.MessageFields.Length); newFields[newFields.Length - 1] = Globals_Game.clock.seasons[season] + ", " + year; this.entryDetails.MessageFields = newFields; this.replied = true; // mark proposal as replied if (proposalAccepted) { this.entryDetails.MessageFields[this.entryDetails.MessageFields.Length - 2] = "ACCEPTED"; } else { this.entryDetails.MessageFields[this.entryDetails.MessageFields.Length - 2] = "REJECTED"; } // if accepted, process engagement if (proposalAccepted) { myProposalReply.ProcessEngagement(); } } return(success); }
public void Listen() { while (server.Status == NetPeerStatus.Running && !ctSource.Token.IsCancellationRequested) { NetIncomingMessage im; WaitHandle.WaitAny(new WaitHandle[] { server.MessageReceivedEvent, ctSource.Token.WaitHandle }); while ((im = server.ReadMessage()) != null && !ctSource.Token.IsCancellationRequested) { switch (im.MessageType) { case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.ErrorMessage: case NetIncomingMessageType.WarningMessage: Globals_Server.logError("Recieved warning message: " + im.ReadString()); break; case NetIncomingMessageType.VerboseDebugMessage: case NetIncomingMessageType.Data: { #if DEBUG Console.WriteLine("SERVER: recieved data message"); #endif if (!clientConnections.ContainsKey(im.SenderConnection)) { //error im.SenderConnection.Disconnect("Not recognised"); return; } Client c = clientConnections[im.SenderConnection]; if (c.alg != null) { im.Decrypt(c.alg); } ProtoMessage m = null; //global::ProtoMessage.ProtoMessage y = null; using (MemoryStream ms = new MemoryStream(im.Data)) { try { //y = Serializer.DeserializeWithLengthPrefix<global::ProtoMessage.ProtoMessage>(ms, //PrefixStyle.Fixed32); m = Serializer.DeserializeWithLengthPrefix <ProtoMessage>(ms, PrefixStyle.Fixed32); } catch (Exception e) { NetOutgoingMessage errorMessage = server.CreateMessage( "Failed to deserialise message. The message may be incorrect, or the decryption may have failed."); if (c.alg != null) { errorMessage.Encrypt(c.alg); } server.SendMessage(errorMessage, im.SenderConnection, NetDeliveryMethod.ReliableOrdered); Globals_Server.logError("Failed to deserialize message for client: " + c.username); } } if (m == null /*&& y == null*/) { string error = "Recieved null message from " + im.SenderEndPoint.ToString(); if (clientConnections.ContainsKey(im.SenderConnection)) { error += ", recognised client " + clientConnections[im.SenderConnection]; } else { error += ", unrecognised client (possible ping)"; } error += ". Data: " + im.ReadString(); Globals_Server.logError(error); break; } if (m.ActionType == Actions.LogIn) { ProtoLogIn login = m as ProtoLogIn; if (login == null) { im.SenderConnection.Disconnect("Not login"); return; } lock (ServerLock) { if (LogInManager.VerifyUser(c.username, login.userSalt)) { if (LogInManager.ProcessLogIn(login, c)) { string log = c.username + " logs in from " + im.SenderEndPoint.ToString(); Globals_Server.logEvent(log); } } else { ProtoMessage reply = new ProtoMessage { ActionType = Actions.LogIn, ResponseType = DisplayMessages.LogInFail }; im.SenderConnection.Disconnect("Authentication Fail"); } } } // temp for testing, should validate connection first else if (clientConnections.ContainsKey(im.SenderConnection)) { if (Globals_Game.IsObserver(c)) { ProcessMessage(m, im.SenderConnection); ProtoClient clientDetails = new ProtoClient(c); clientDetails.ActionType = Actions.Update; SendViaProto(clientDetails, im.SenderConnection, c.alg); } else { im.SenderConnection.Disconnect("Not logged in- Disconnecting"); } } /*//IF Y ACTION * if (y.ActionType == global::ProtoMessage.Actions.LogIn) * { * global::ProtoMessage.Client forCheck = new global::ProtoMessage.Client(c.username, c.myPlayerCharacter.playerID); * global::ProtoMessage.ProtoLogIn login = y as global::ProtoMessage.ProtoLogIn; * if (login == null) * { * im.SenderConnection.Disconnect("Not login"); * return; * } * lock (ServerLock) * { * if (LogInManager.VerifyUser(c.username, login.userSalt)) * { * if (LogInManager.ProcessLogIn(login, forCheck, true)) * { * string log = c.username + " logs in from " + im.SenderEndPoint.ToString(); * Globals_Server.logEvent(log); * } * } * else * { * ProtoMessage reply = new ProtoMessage * { * ActionType = Actions.LogIn, * ResponseType = DisplayMessages.LogInFail * }; * im.SenderConnection.Disconnect("Authentication Fail"); * } * } * } * // temp for testing, should validate connection first * else if (clientConnections.ContainsKey(im.SenderConnection)) * { * if (Globals_Game.IsObserver(c)) * { * ProcessMessage(y, im.SenderConnection); * ProtoClient clientDetails = new ProtoClient(c); * clientDetails.ActionType = Actions.Update; * SendViaProto(clientDetails, im.SenderConnection, c.alg); * } * else * { * im.SenderConnection.Disconnect("Not logged in- Disconnecting"); * } * }*/ } break; case NetIncomingMessageType.StatusChanged: byte stat = im.ReadByte(); NetConnectionStatus status = NetConnectionStatus.None; if (Enum.IsDefined(typeof(NetConnectionStatus), Convert.ToInt32(stat))) { status = (NetConnectionStatus)stat; } else { Globals_Server.logError("Failure to parse byte " + stat + " to NetConnectionStatus for endpoint " + im.ReadIPEndPoint()); } if (status == NetConnectionStatus.Disconnected) { if (clientConnections.ContainsKey(im.SenderConnection)) { Disconnect(im.SenderConnection); } } break; case NetIncomingMessageType.ConnectionApproval: { string senderID = im.ReadString(); string text = im.ReadString(); Client client; Globals_Server.Clients.TryGetValue(senderID, out client); if (client != null) { ProtoLogIn logIn; if (!LogInManager.AcceptConnection(client, text, out logIn)) { im.SenderConnection.Deny(); } else { NetOutgoingMessage msg = server.CreateMessage(); MemoryStream ms = new MemoryStream(); // Include X509 certificate as bytes for client to validate Serializer.SerializeWithLengthPrefix <ProtoLogIn>(ms, logIn, PrefixStyle.Fixed32); msg.Write(ms.GetBuffer()); clientConnections.Add(im.SenderConnection, client); client.conn = im.SenderConnection; im.SenderConnection.Approve(msg); server.FlushSendQueue(); Globals_Server.logEvent("Accepted connection from " + client.username); } } else { im.SenderConnection.Deny("unrecognised"); } } break; case NetIncomingMessageType.ConnectionLatencyUpdated: break; default: Globals_Server.logError("Received unrecognised incoming message type: " + im.MessageType); break; } server.Recycle(im); } } #if DEBUG Globals_Server.logEvent("Server listening thread exits"); #endif }
/// <summary> /// Implements the processes involved in a battle between two armies in the field /// </summary> /// <returns>bool indicating whether attacking army is victorious</returns> /// <remarks> /// Predicate: assumes attacker has sufficient days /// Predicate: assumes attacker has leader /// Predicate: assumes attacker in same fief as defender /// Predicate: assumes defender not besieged in keep /// Predicate: assumes attacker and defender not same army /// </remarks> /// <param name="attacker">The attacking army</param> /// <param name="defender">The defending army</param> /// <param name="circumstance">string indicating circumstance of battle</param> public static bool GiveBattle(Army attacker, Army defender, out ProtoBattle battleResults, string circumstance = "battle") { Contract.Requires(attacker != null && defender != null && circumstance != null); battleResults = new ProtoBattle(); bool attackerVictorious = false; bool battleHasCommenced = false; bool attackerLeaderDead = false; bool defenderLeaderDead = false; // check if losing army has disbanded bool attackerDisbanded = false; bool defenderDisbanded = false; bool siegeRaised = false; uint[] battleValues = new uint[2]; double[] casualtyModifiers = new double[2]; double statureChange = 0; // if applicable, get siege Siege thisSiege = null; string thisSiegeID = defender.CheckIfBesieger(); if (!String.IsNullOrWhiteSpace(thisSiegeID)) { // get siege thisSiege = Globals_Game.siegeMasterList[thisSiegeID]; } // get starting troop numbers uint attackerStartTroops = attacker.CalcArmySize(); uint defenderStartTroops = defender.CalcArmySize(); uint attackerCasualties = 0; uint defenderCasualties = 0; // get leaders Character attackerLeader = attacker.GetLeader(); Character defenderLeader = defender.GetLeader(); // if(attackerLeader!=null) { battleResults.attackerLeader = attackerLeader.firstName + " " + attackerLeader.familyName; // } // if(defenderLeader!=null) { battleResults.defenderLeader = defenderLeader.firstName + " " + defenderLeader.familyName; // } battleResults.attackerOwner = attacker.GetOwner().firstName + " " + attacker.GetOwner().familyName; battleResults.defenderOwner = defender.GetOwner().firstName + " " + defender.GetOwner().familyName; battleResults.battleLocation = attacker.GetLocation().id; // introductory text for message switch (circumstance) { case "pillage": battleResults.circumstance = 1; break; case "siege": battleResults.circumstance = 2; break; default: battleResults.circumstance = 0; break; } // get battle values for both armies battleValues = attacker.CalculateBattleValues(defender); // check if attacker has managed to bring defender to battle // case 1: defending army sallies during siege to attack besieger = battle always occurs if (circumstance.Equals("siege")) { battleHasCommenced = true; } // case 2: defending militia attacks pillaging army during pollage = battle always occurs else if (circumstance.Equals("pillage")) { battleHasCommenced = true; } // case 3: defender aggression and combatOdds allows battle else if (defender.aggression != 0) { if (defender.aggression == 1) { // get odds int battleOdds = Battle.GetBattleOdds(attacker, defender); // if odds OK, give battle if (battleOdds <= defender.combatOdds) { battleHasCommenced = true; } // if not, check for battle else { battleHasCommenced = Battle.BringToBattle(battleValues[0], battleValues[1], circumstance); if (!battleHasCommenced) { defender.ProcessRetreat(1); } } } else { battleHasCommenced = true; } } // otherwise, check to see if the attacker can bring the defender to battle else { battleHasCommenced = Battle.BringToBattle(battleValues[0], battleValues[1], circumstance); if (!battleHasCommenced) { defender.ProcessRetreat(1); } } battleResults.battleTookPlace = battleHasCommenced; if (battleHasCommenced) { List <string> disbandedArmies = new List <string>(); List <string> retreatedArmies = new List <string>(); List <string> deadCharacters = new List <string>(); // WHO HAS WON? // calculate if attacker has won attackerVictorious = Battle.DecideBattleVictory(battleValues[0], battleValues[1]); // UPDATE STATURE if (attackerVictorious) { statureChange = 0.8 * (defender.CalcArmySize() / Convert.ToDouble(10000)); battleResults.statureChangeAttacker = statureChange; attacker.GetOwner().AdjustStatureModifier(statureChange); statureChange = -0.5 * (attacker.CalcArmySize() / Convert.ToDouble(10000)); battleResults.statureChangeDefender = statureChange; defender.GetOwner().AdjustStatureModifier(statureChange); } else { statureChange = 0.8 * (attacker.CalcArmySize() / Convert.ToDouble(10000)); battleResults.statureChangeDefender = statureChange; defender.GetOwner().AdjustStatureModifier(statureChange); statureChange = -0.5 * (defender.CalcArmySize() / Convert.ToDouble(10000)); battleResults.statureChangeAttacker = statureChange; attacker.GetOwner().AdjustStatureModifier(statureChange); } // CASUALTIES // calculate troop casualties for both sides casualtyModifiers = Battle.CalculateBattleCasualties(attackerStartTroops, defenderStartTroops, battleValues[0], battleValues[1], attackerVictorious); uint totalAttackTroopsLost = 0; uint totalDefendTroopsLost = 0; // if losing side sustains >= 50% casualties, disbands if (attackerVictorious) { // either indicate losing army to be disbanded if (casualtyModifiers[1] >= 0.5) { defenderDisbanded = true; disbandedArmies.Add(defender.owner); totalDefendTroopsLost = defender.CalcArmySize(); } // OR apply troop casualties to losing army else { totalDefendTroopsLost = defender.ApplyTroopLosses(casualtyModifiers[1]); } // apply troop casualties to winning army totalAttackTroopsLost = attacker.ApplyTroopLosses(casualtyModifiers[0]); } else { if (casualtyModifiers[0] >= 0.5) { attackerDisbanded = true; disbandedArmies.Add(attacker.owner); totalAttackTroopsLost = attacker.CalcArmySize(); } else { totalAttackTroopsLost = attacker.ApplyTroopLosses(casualtyModifiers[0]); } totalDefendTroopsLost = defender.ApplyTroopLosses(casualtyModifiers[1]); } battleResults.attackerCasualties = totalAttackTroopsLost; battleResults.defenderCasualties = totalDefendTroopsLost; // UPDATE TOTAL SIEGE LOSSES, if appropriate // NOTE: the defender in this battle is the attacker in the siege and v.v. if (thisSiege != null) { // update total siege attacker (defender in this battle) losses thisSiege.totalCasualtiesAttacker += Convert.ToInt32(totalDefendTroopsLost); // update total siege defender (attacker in this battle) losses if (circumstance.Equals("siege")) { thisSiege.totalCasualtiesDefender += Convert.ToInt32(totalAttackTroopsLost); } } // get casualty figures (for message) if (!attackerDisbanded) { // get attacker casualties attackerCasualties = totalAttackTroopsLost; } if (!defenderDisbanded) { // get defender casualties defenderCasualties = totalDefendTroopsLost; } // DAYS // adjust days // NOTE: don't adjust days if is a siege (will be deducted elsewhere) if (!circumstance.Equals("siege")) { if (attackerLeader != null) { attackerLeader.AdjustDays(1); } // need to check for defender having no leader if (defenderLeader != null) { defenderLeader.AdjustDays(1); } else { defender.days -= 1; } } // RETREATS // create array of armies (for easy processing) Army[] bothSides = { attacker, defender }; // check if either army needs to retreat int[] retreatDistances = Battle.CheckForRetreat(attacker, defender, casualtyModifiers[0], casualtyModifiers[1], attackerVictorious); // if is pillage or siege, attacking army (the fief's army) doesn't retreat // if is pillage, the defending army (the pillagers) always retreats if has lost if (circumstance.Equals("pillage") || circumstance.Equals("siege")) { retreatDistances[0] = 0; } if (circumstance.Equals("pillage")) { if (attackerVictorious) { retreatDistances[1] = 1; } } // if have retreated, perform it for (int i = 0; i < retreatDistances.Length; i++) { if (retreatDistances[i] > 0) { bothSides[i].ProcessRetreat(retreatDistances[i]); } } // If attacker has retreated add to retreat list if (retreatDistances[0] > 0) { retreatedArmies.Add(battleResults.attackerOwner); } // If defender retreated add to retreat list if (retreatDistances[1] > 0) { retreatedArmies.Add(battleResults.defenderOwner); } // PC/NPC INJURIES/DEATHS // check if any PCs/NPCs have been wounded or killed bool characterDead = false; // 1. ATTACKER uint friendlyBV = battleValues[0]; uint enemyBV = battleValues[1]; // if army leader a PC, check entourage if (attackerLeader is PlayerCharacter) { for (int i = 0; i < (attackerLeader as PlayerCharacter).myNPCs.Count; i++) { if ((attackerLeader as PlayerCharacter).myNPCs[i].inEntourage) { characterDead = (attackerLeader as PlayerCharacter).myNPCs[i].CalculateCombatInjury(casualtyModifiers[0]); } // process death, if applicable if (characterDead) { (attackerLeader as PlayerCharacter).myNPCs[i].ProcessDeath("injury"); } } } // check army leader if (attackerLeader != null) { attackerLeaderDead = attackerLeader.CalculateCombatInjury(casualtyModifiers[0]); } // process death, if applicable if (attackerLeaderDead) { deadCharacters.Add(attackerLeader.firstName + " " + attackerLeader.familyName); Character newLeader = null; // if is pillage, do NOT elect new leader for attacking army if (!circumstance.Equals("pillage")) { // if possible, elect new leader from entourage if (attackerLeader is PlayerCharacter) { if ((attackerLeader as PlayerCharacter).myNPCs.Count > 0) { // get new leader newLeader = (attackerLeader as PlayerCharacter).ElectNewArmyLeader(); } } // assign newLeader (can assign null leader if none found) attacker.AssignNewLeader(newLeader); } } else { // if pillage, if fief's army loses, make sure bailiff always returns to keep if (circumstance.Equals("pillage")) { if (!attackerVictorious) { attackerLeader.inKeep = true; } } } // 2. DEFENDER // need to check if defending army had a leader if (defenderLeader != null) { // if army leader a PC, check entourage if (defenderLeader is PlayerCharacter) { for (int i = 0; i < (defenderLeader as PlayerCharacter).myNPCs.Count; i++) { if ((defenderLeader as PlayerCharacter).myNPCs[i].inEntourage) { characterDead = (defenderLeader as PlayerCharacter).myNPCs[i].CalculateCombatInjury(casualtyModifiers[1]); } // process death, if applicable if (characterDead) { (defenderLeader as PlayerCharacter).myNPCs[i].ProcessDeath("injury"); } } } // check army leader defenderLeaderDead = defenderLeader.CalculateCombatInjury(casualtyModifiers[1]); // process death, if applicable if (defenderLeaderDead) { deadCharacters.Add(defenderLeader.firstName + " " + defenderLeader.familyName); Character newLeader = null; // if possible, elect new leader from entourage if (defenderLeader is PlayerCharacter) { if ((defenderLeader as PlayerCharacter).myNPCs.Count > 0) { // get new leader newLeader = (defenderLeader as PlayerCharacter).ElectNewArmyLeader(); } } // assign newLeader (can assign null leader if none found) defender.AssignNewLeader(newLeader); } } battleResults.deaths = deadCharacters.ToArray(); battleResults.retreatedArmies = retreatedArmies.ToArray(); battleResults.attackerVictorious = attackerVictorious; // check for SIEGE RELIEF if (thisSiege != null) { battleResults.isSiege = true; battleResults.siegeBesieger = thisSiege.GetBesiegingPlayer().firstName + " " + thisSiege.GetBesiegingPlayer().familyName; battleResults.siegeDefender = thisSiege.GetDefendingPlayer().firstName + " " + thisSiege.GetDefendingPlayer().familyName; // attacker (relieving army) victory or defender (besieging army) retreat = relief if ((attackerVictorious) || (retreatDistances[1] > 0)) { // indicate siege raised siegeRaised = true; battleResults.siegeRaised = true; } // check to see if siege raised due to death of siege owner with no heir else if ((defenderLeaderDead) && ((defenderLeader as PlayerCharacter) == thisSiege.GetBesiegingPlayer())) { // get siege owner's heir Character thisHeir = (defenderLeader as PlayerCharacter).GetHeir(); if (thisHeir == null) { battleResults.DefenderDeadNoHeir = true; // indicate siege raised siegeRaised = true; } } } } // =================== construct and send JOURNAL ENTRY // ID uint entryID = Globals_Game.GetNextJournalEntryID(); // personae // personae tags vary depending on circumstance string attackOwnTag = "|attackerOwner"; string attackLeadTag = "|attackerLeader"; string defendOwnTag = "|defenderOwner"; string defendLeadTag = "|defenderLeader"; if ((circumstance.Equals("pillage")) || (circumstance.Equals("siege"))) { attackOwnTag = "|sallyOwner"; attackLeadTag = "|sallyLeader"; defendOwnTag = "|defenderAgainstSallyOwner"; defendLeadTag = "|defenderAgainstSallyLeader"; } List <string> tempPersonae = new List <string>(); tempPersonae.Add(defender.GetOwner().charID + defendOwnTag); if (attackerLeader != null) { tempPersonae.Add(attackerLeader.charID + attackLeadTag); } if (defenderLeader != null) { tempPersonae.Add(defenderLeader.charID + defendLeadTag); } tempPersonae.Add(attacker.GetOwner().charID + attackOwnTag); tempPersonae.Add(attacker.GetLocation().owner.charID + "|fiefOwner"); if ((!circumstance.Equals("pillage")) && (!circumstance.Equals("siege"))) { tempPersonae.Add("all|all"); } string[] battlePersonae = tempPersonae.ToArray(); // location string battleLocation = attacker.GetLocation().id; // put together new journal entry JournalEntry battleResult = new JournalEntry(entryID, Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, battlePersonae, "battle", battleResults, loc: battleLocation); // add new journal entry to pastEvents Globals_Game.AddPastEvent(battleResult); // display pop-up informational message battleResults.ActionType = Actions.Update; battleResults.ResponseType = DisplayMessages.BattleResults; if (battleHasCommenced) { Globals_Game.UpdatePlayer(defender.GetOwner().playerID, DisplayMessages.BattleBringSuccess, new string[] { battleResults.attackerOwner }); } else { Globals_Game.UpdatePlayer(defender.GetOwner().playerID, DisplayMessages.BattleBringFail, new string[] { battleResults.attackerOwner }); } // end siege if appropriate if (siegeRaised) { //HACK thisSiege.SiegeEnd(false, DisplayMessages.BattleResults, new string[] { DisplaySiegeResults(battleResults) }); thisSiege = null; // ensure if siege raised correct value returned to Form1.siegeReductionRound method if (circumstance.Equals("siege")) { attackerVictorious = true; } } // process leader deaths if (defenderLeaderDead) { defenderLeader.ProcessDeath("injury"); } else if (attackerLeaderDead) { attackerLeader.ProcessDeath("injury"); } // DISBANDMENT // if is pillage, attacking (temporary) army always disbands after battle if (circumstance.Equals("pillage")) { attackerDisbanded = true; } // process army disbandings (after all other functions completed) if (attackerDisbanded) { attacker.DisbandArmy(); attacker = null; } if (defenderDisbanded) { defender.DisbandArmy(); defender = null; } return(attackerVictorious); }
/// <summary> /// Generates a new NPC based on parents' statistics /// </summary> /// <returns>NonPlayerCharacter or null</returns> /// <param name="mummy">The new NPC's mother</param> /// <param name="daddy">The new NPC's father</param> public static NonPlayerCharacter GenerateNewNPC(Character mummy, Character daddy) { NonPlayerCharacter newNPC = new NonPlayerCharacter(); // charID newNPC.charID = Globals_Game.GetNextCharID(); // first name newNPC.firstName = "Baby"; // family name newNPC.familyName = daddy.familyName; // date of birth newNPC.birthDate = new Tuple <uint, byte>(Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason); // sex newNPC.isMale = Birth.GenerateSex(); // nationality newNPC.nationality = daddy.nationality; // whether is alive newNPC.isAlive = true; // maxHealth newNPC.maxHealth = Birth.GenerateKeyCharacteristics(mummy.maxHealth, daddy.maxHealth); // virility newNPC.virility = Birth.GenerateKeyCharacteristics(mummy.virility, daddy.virility); // goTo queue newNPC.goTo = new Queue <Fief>(); // language newNPC.language = daddy.language; // days left newNPC.days = 90; // stature modifier newNPC.statureModifier = 0; // management newNPC.management = Birth.GenerateKeyCharacteristics(mummy.management, daddy.management); // combat newNPC.combat = Birth.GenerateKeyCharacteristics(mummy.combat, daddy.combat); // traits newNPC.traits = Birth.GenerateTraitSetFromParents(mummy.traits, daddy.traits, newNPC.isMale); // if in keep newNPC.inKeep = mummy.inKeep; // if pregnant newNPC.isPregnant = false; // familyID newNPC.familyID = daddy.familyID; // spouse newNPC.spouse = null; // father newNPC.father = daddy.charID; // mother newNPC.mother = mummy.charID; // fiancee newNPC.fiancee = null; // location newNPC.location = null; // titles newNPC.myTitles = new List <string>(); // armyID newNPC.armyID = null; // ailments newNPC.ailments = new Dictionary <string, Ailment>(); // employer newNPC.employer = null; // salary/allowance newNPC.salary = 0; // lastOffer (will remain empty for family members) newNPC.lastOffer = new Dictionary <string, uint>(); // inEntourage newNPC.setEntourage(false); // isHeir newNPC.isHeir = false; return(newNPC); }
/// <summary> /// Processes the actions involved with a marriage /// </summary> /// <returns>bool indicating whether engagement was processed successfully</returns> public bool ProcessMarriage() { bool success = false; // get interested parties PlayerCharacter headOfFamilyBride = null; PlayerCharacter headOfFamilyGroom = null; Character bride = null; Character groom = null; for (int i = 0; i < this.personae.Length; i++) { string thisPersonae = this.personae[i]; string[] thisPersonaeSplit = thisPersonae.Split('|'); switch (thisPersonaeSplit[1]) { case "headOfFamilyGroom": headOfFamilyGroom = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; break; case "headOfFamilyBride": headOfFamilyBride = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; break; case "bride": bride = Globals_Game.npcMasterList[thisPersonaeSplit[0]]; break; case "groom": if (Globals_Game.pcMasterList.ContainsKey(thisPersonaeSplit[0])) { groom = Globals_Game.pcMasterList[thisPersonaeSplit[0]]; } else if (Globals_Game.npcMasterList.ContainsKey(thisPersonaeSplit[0])) { groom = Globals_Game.npcMasterList[thisPersonaeSplit[0]]; } break; default: break; } } // ID uint marriageID = Globals_Game.GetNextJournalEntryID(); // date uint year = Globals_Game.clock.currentYear; byte season = Globals_Game.clock.currentSeason; // personae string headOfFamilyBrideEntry = headOfFamilyBride.charID + "|headOfFamilyBride"; string headOfFamilyGroomEntry = headOfFamilyGroom.charID + "|headOfFamilyGroom"; string thisBrideEntry = bride.charID + "|bride"; string thisGroomEntry = groom.charID + "|groom"; string allEntry = "all|all"; string[] marriagePersonae = new string[] { headOfFamilyGroomEntry, headOfFamilyBrideEntry, thisBrideEntry, thisGroomEntry, allEntry }; // type string type = "marriage"; string[] fields = new string[3]; fields[0] = groom.firstName + " " + groom.familyName; fields[1] = bride.firstName + " " + groom.familyName; fields[2] = bride.familyName; // description ProtoMessage marriage = new ProtoMessage(); marriage.MessageFields = fields; marriage.ResponseType = DisplayMessages.JournalMarriage; // create and add a marriage entry to the pastEvents journal JournalEntry marriageEntry = new JournalEntry(marriageID, year, season, marriagePersonae, type, marriage, null); success = Globals_Game.AddPastEvent(marriageEntry); if (success) { // remove fiancees bride.fiancee = null; groom.fiancee = null; // add spouses bride.spouse = groom.charID; groom.spouse = bride.charID; // change wife's family bride.familyID = groom.familyID; bride.familyName = groom.familyName; // switch myNPCs headOfFamilyBride.myNPCs.Remove(bride as NonPlayerCharacter); headOfFamilyGroom.myNPCs.Add(bride as NonPlayerCharacter); // move wife to groom's location bride.location = groom.location; // check to see if headOfFamilyBride should receive increase in stature // get highest rank for headOfFamilyBride and headOfFamilyGroom Rank brideHighestRank = headOfFamilyBride.GetHighestRank(); Rank groomHighestRank = headOfFamilyGroom.GetHighestRank(); // compare ranks if ((brideHighestRank != null) && (groomHighestRank != null)) { if (groomHighestRank.id < brideHighestRank.id) { headOfFamilyBride.AdjustStatureModifier((brideHighestRank.id - groomHighestRank.id) * 0.4); } } } return(success); }
/// <summary> /// Allows an attacking army to lay siege to an enemy fief /// </summary> /// <param name="attacker">The attacking army</param> /// <param name="target">The fief to be besieged</param> public static Siege SiegeStart(Army attacker, Fief target) { Army defenderGarrison = null; Army defenderAdditional = null; // check for existence of army in keep for (int i = 0; i < target.armies.Count; i++) { // get army Army armyInFief = Globals_Game.armyMasterList[target.armies[i]]; // check is in keep Character armyLeader = armyInFief.GetLeader(); if (armyLeader != null) { if (armyLeader.inKeep) { // check owner is same as that of fief (i.e. can help in siege) if (armyInFief.GetOwner() == target.owner) { defenderAdditional = armyInFief; break; } } } } // create defending force defenderGarrison = target.CreateDefendingArmy(); // get the minumum days of all army objects involved double minDays = Math.Min(attacker.days, defenderGarrison.days); if (defenderAdditional != null) { minDays = Math.Min(minDays, defenderAdditional.days); } // get defenderAdditional ID, or null if no defenderAdditional string defAddID = null; if (defenderAdditional != null) { defAddID = defenderAdditional.armyID; } // create siege object Siege mySiege = new Siege(Globals_Game.GetNextSiegeID(), Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, attacker.GetOwner().charID, target.owner.charID, attacker.armyID, defenderGarrison.armyID, target.id, minDays, target.keepLevel, defAdd: defAddID); // add to master list Globals_Game.siegeMasterList.Add(mySiege.siegeID, mySiege); // add to siege owners mySiege.GetBesiegingPlayer().mySieges.Add(mySiege.siegeID); mySiege.GetDefendingPlayer().mySieges.Add(mySiege.siegeID); // add to fief target.siege = mySiege.siegeID; // reduce expenditures in fief, except for garrison target.infrastructureSpendNext = 0; target.keepSpendNext = 0; target.officialsSpendNext = 0; // update days (NOTE: siege.days will be updated in syncDays) mySiege.totalDays++; // sychronise days mySiege.SyncSiegeDays(mySiege.days - 1); // =================== construct and send JOURNAL ENTRY // ID uint entryID = Globals_Game.GetNextJournalEntryID(); // personae List <string> tempPersonae = new List <string>(); tempPersonae.Add("all|all"); tempPersonae.Add(mySiege.GetDefendingPlayer().charID + "|fiefOwner"); tempPersonae.Add(mySiege.GetBesiegingPlayer().charID + "|attackerOwner"); tempPersonae.Add(attacker.GetLeader().charID + "|attackerLeader"); // get defenderLeader Character defenderLeader = defenderGarrison.GetLeader(); if (defenderLeader != null) { tempPersonae.Add(defenderLeader.charID + "|defenderGarrisonLeader"); } // get additional defending leader Character addDefendLeader = null; if (defenderAdditional != null) { addDefendLeader = defenderAdditional.GetLeader(); if (addDefendLeader != null) { tempPersonae.Add(addDefendLeader.charID + "|defenderAdditionalLeader"); } } string[] siegePersonae = tempPersonae.ToArray(); // location string siegeLocation = mySiege.GetFief().id; // description string[] fields = new string[6]; fields[0] = mySiege.GetBesiegingPlayer().firstName + " " + mySiege.GetBesiegingPlayer().familyName; fields[1] = attacker.GetLeader().firstName + " " + attacker.GetLeader().familyName; fields[2] = mySiege.GetFief().name; fields[3] = mySiege.GetDefendingPlayer().firstName + " " + mySiege.GetDefendingPlayer().familyName; fields[4] = fields[5] = ""; if (defenderLeader != null) { fields[4] = "The defending garrison is led by " + defenderLeader.firstName + " " + defenderLeader.familyName + "."; } if (addDefendLeader != null) { fields[5] = "Additional defending forces are led by " + addDefendLeader.firstName + " " + addDefendLeader.familyName + "."; } ProtoMessage siege = new ProtoMessage(); siege.MessageFields = fields; siege.ResponseType = DisplayMessages.PillageInitiateSiege; // put together new journal entry JournalEntry siegeResult = new JournalEntry(entryID, Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, siegePersonae, "siege", siege, loc: siegeLocation); // add new journal entry to pastEvents Globals_Game.AddPastEvent(siegeResult); return(mySiege); }
/// <summary> /// Inserts the supplied PlayerCharacter's ID into the Position's officeHolder variable /// </summary> /// <param name="newPositionHolder">PlayerCharacter being assigned to the Position</param> public void BestowPosition(PlayerCharacter newPositionHolder) { PlayerCharacter oldPositionHolder = null; // remove existing holder if necessary if (!String.IsNullOrWhiteSpace(this.officeHolder)) { // get current holder if (Globals_Game.pcMasterList.ContainsKey(this.officeHolder)) { oldPositionHolder = Globals_Game.pcMasterList[this.officeHolder]; } // remove from position this.RemoveFromOffice(oldPositionHolder); } // assign position this.officeHolder = newPositionHolder.charID; // update stature newPositionHolder.AdjustStatureModifier(this.stature); // CREATE JOURNAL ENTRY // get interested parties bool success = true; PlayerCharacter king = this.GetKingdom().owner; // ID uint entryID = Globals_Game.GetNextJournalEntryID(); // date uint year = Globals_Game.clock.currentYear; byte season = Globals_Game.clock.currentSeason; // personae List <string> tempPersonae = new List <string>(); tempPersonae.Add("all|all"); tempPersonae.Add(king.charID + "|king"); tempPersonae.Add(newPositionHolder.charID + "|newPositionHolder"); if (oldPositionHolder != null) { tempPersonae.Add(oldPositionHolder.charID + "|oldPositionHolder"); } string[] thisPersonae = tempPersonae.ToArray(); // type string type = "grantPosition"; // description String[] fields = new string[] { this.title[0].name, king.firstName + " " + king.familyName, newPositionHolder.firstName + " " + newPositionHolder.familyName, "" }; if (oldPositionHolder != null) { fields[3] = "; This has necessitated the removal of " + oldPositionHolder.firstName + " " + oldPositionHolder.familyName + " from the position"; } ProtoMessage bestowPosition = new ProtoMessage(); bestowPosition.MessageFields = fields; bestowPosition.ResponseType = DisplayMessages.RankTitleTransfer; // create and add a journal entry to the pastEvents journal JournalEntry thisEntry = new JournalEntry(entryID, year, season, thisPersonae, type, bestowPosition); success = Globals_Game.AddPastEvent(thisEntry); }
/// <summary> /// Implements the processes involved in the pillage of a fief by an army /// </summary> /// <param name="a">The pillaging army</param> /// <param name="f">The fief being pillaged</param> public static ProtoMessage PillageFief(Army a, Fief f) { ProtoMessage result = new ProtoMessage(); bool pillageCancelled = false; bool bailiffPresent = false; Army fiefArmy = null; // check if bailiff present in fief (he'll lead the army) if (f.bailiff != null) { for (int i = 0; i < f.charactersInFief.Count; i++) { if (f.charactersInFief[i] == f.bailiff) { bailiffPresent = true; break; } } } // if bailiff is present, create an army and attempt to give battle // no bailiff = no leader = pillage is unopposed by defending forces if (bailiffPresent) { // create temporary army for battle fiefArmy = f.CreateDefendingArmy(); // give battle and get result ProtoBattle battleResults; pillageCancelled = Battle.GiveBattle(fiefArmy, a, out battleResults, circumstance: "pillage"); if (pillageCancelled) { string toDisplay = "The pillaging force has been forced to retreat by the fief's defenders!"; result.ResponseType = DisplayMessages.PillageRetreat; // Let owner know that pillage attempt has been thwarted Globals_Game.UpdatePlayer(f.owner.playerID, DisplayMessages.PillageRetreat); return(result); } else { // check still have enough days left if (a.days < 7) { // Inform fief owner pillage attempt thwarted Globals_Game.UpdatePlayer(f.owner.playerID, DisplayMessages.PillageDays); result.ResponseType = DisplayMessages.PillageDays; pillageCancelled = true; return(result); } } } if (!pillageCancelled) { // process pillage return(Pillage_Siege.ProcessPillage(f, a)); } result.ResponseType = DisplayMessages.Success; result.Message = "The pillage was successful"; return(result); }