瀏覽代碼

Stress-testing 800 in-fighting Orcs with all the new Combat rules. Game still runs at under 200ms per action. Given we will never have 800 angry orcs in the same rooms, I think it's fair to assume the game will NEVER be so big that it slows down, specially since normal demand increase will happen with sparse NPCs, where each NPC does not increase the processing demand of the other NPCs (mostly linear increase, while in this case each NPC not only brought its own rules, but also made everyone else's rules harder to execute). Quite happy with results. Blog over.

Reddo 5 年之前
父節點
當前提交
0efcec5da6
共有 6 個文件被更改,包括 62 次插入16 次删除
  1. 2 2
      The Obelisk.haml
  2. 13 9
      app/World/Classes/AI/AIGrudge.ts
  3. 38 0
      app/World/Classes/AI/Combat/BasicCombat.ts
  4. 1 1
      app/World/Settings.ts
  5. 8 3
      content/main.ts
  6. 0 1
      dist/The Obelisk.html

+ 2 - 2
The Obelisk.haml

@@ -82,10 +82,10 @@
                 #roomExits
     -###########
     -# Relative File for Debugging
-    %script{:type => "text/javascript", :charset=>"utf8", :src => "../js/Application.js"}
+    -#%script{:type => "text/javascript", :charset=>"utf8", :src => "../js/Application.js"}
     -###########
     -# Optimized No Debug Data URL
-    -#= "<script id=\"ApplicationJS\" type=\"text/javascript\", charset=\"utf8\", src=\"data:application/javascript," + (URI.encode("(function(){\n" + (File.read "js/Application.js").encode!('UTF-8', 'UTF-8', :invalid => :replace).gsub("console.debug(", "//")) + "\n})()") + "\"></script>";
+    = "<script id=\"ApplicationJS\" type=\"text/javascript\", charset=\"utf8\", src=\"data:application/javascript," + (URI.encode("(function(){\n" + (File.read "js/Application.js").encode!('UTF-8', 'UTF-8', :invalid => :replace).gsub("console.debug(", "//")) + "\n})()") + "\"></script>";
     -###########
     %style{:media=>"screen", :type=>"text/css"}
       = File.read "stylesheets/fonts.css"

+ 13 - 9
app/World/Classes/AI/AIGrudge.ts

@@ -12,15 +12,19 @@ module AIRules {
     export var resultHostile = new ContentMarker("I'll hit you until you drop dead.", true);
 
     export function printGrudgeResult (aggressor : Thing, victim : Person, ...markers : Array<ContentMarker>) {
-        let group = new ContentGroup();
-        let unit = new CombatPokeUnit();
-        group.addUnit(unit);
-        unit.setTarget(victim);
-        unit.setAggressor(aggressor);
-        unit.addMarker(...markers);
+        if (victim.isVisibleTo(WorldState.player)) {
+            let group = new ContentGroup();
+            let unit = new CombatPokeUnit();
+            group.addUnit(unit);
+            unit.setTarget(victim);
+            unit.setAggressor(aggressor);
+            unit.addMarker(...markers);
 
-        victim.AI.warnedTimes++;
-        Elements.CurrentTurnHandler.printAsContent(new Say(...CombatPokeDescription.getDescription(group)));
+            if (aggressor == WorldState.player) {
+                victim.AI.warnedTimes++;
+            }
+            Elements.CurrentTurnHandler.printAsContent(new Say(...CombatPokeDescription.getDescription(group)));
+        }
     }
 
     export var Grudge = AI.rules.createAndAddRule({
@@ -54,10 +58,10 @@ module AIRules {
                         }
 
                         printGrudgeResult(action.actor, person, actionLevel, result);
-
                         if (result == resultRetaliate) {
                             return new ActionAttack(person, action.actor);
                         }
+                        return new ActionWait(person); // we talked so we shouldn't move further
                     }
                 }
             }

+ 38 - 0
app/World/Classes/AI/Combat/BasicCombat.ts

@@ -15,4 +15,42 @@ module AIRules {
     });
     AI.combatRules.addRule(standUp);
     AI.rules.addRule(standUp);
+
+
+    export var Hunt = AI.rules.createAndAddRule({
+        name: "Follow based on grudge",
+        firstPriority: AIRules.PRIORITY_ACTING_ON_SITUATION,
+        priority: AIRules.PRIORITY_ACTING_ON_IDLE,
+        code: (runner: RulebookRunner<Person>) => {
+            let person = runner.noun;
+            let hostiles = [...runner.noun.AI.hostileTargets].sort((a, b) => {
+                return person.AI.getHostilityTo(b) - person.AI.getHostilityTo(a);
+            });
+            for (let i = 0; i < hostiles.length; i++) {
+                if (ActionFollow.isCloseEnough(person, hostiles[i])) {
+                    return new ActionFollow(person, hostiles[i]);
+                }
+            }
+        },
+        conditions: (runner: RulebookRunner<Person>) => {
+            return runner.noun.AI.hostileTargets.length > 0;
+        }
+    });
+
+
+    export var rngHit = AI.rules.createAndAddRule({
+        name: "Hit someone else RNGly",
+        firstPriority: AIRules.PRIORITY_ACTING_ON_IDLE,
+        priority: AIRules.PRIORITY_ACTING_ON_SITUATION,
+        code: (runner: RulebookRunner<Person>) => {
+            for (let i = 0; i < runner.noun.AI.newNoticed.length; i++) {
+                if (runner.noun.AI.newNoticed[i] instanceof Person && runner.noun.AI.newNoticed[i] != WorldState.player) {
+                    return new ActionAttack(runner.noun, runner.noun.AI.newNoticed[i]);
+                }
+            }
+        },
+        conditions: (runner: RulebookRunner<Person>) => {
+            return (Math.random() * 100) >= 50;
+        }
+    });
 }

+ 1 - 1
app/World/Settings.ts

@@ -3,7 +3,7 @@ module Settings {
     var debugEmpty = () => {};
 
     export var hardDebug = false;
-    export var sayTurnTime = false;
+    export var sayTurnTime = true;
 
     export function setDebug (isDebug : boolean) {
         if (isDebug) {

+ 8 - 3
content/main.ts

@@ -241,7 +241,7 @@ for (let i = 0; i < 0; i++) {
 }
 let randomOrc;
 let randomOrc2;
-for (let i = 0; i < 2; i++) {
+for (let i = 0; i < 800; i++) {
     let orc = new OrcDebugger();
     randomOrc = orc;
     if (randomOrc2 == undefined) {
@@ -344,7 +344,7 @@ spitroast.addUnit()
         return say;
     })
     .addUnit()
-    .setActor(WorldState.player)
+    .setActor(Person)
     .setTarget(Person)
     .addMarker(AdaptiveDifferential.FULLYADAPTIVE(CombatHit.HIT, CombatHit.CRITICAL, CombatHit.MISS))
     .addMarker(AdaptiveDifferential.FULLYADAPTIVE(CombatResult.KILLED, CombatResult.KNOCKED, CombatResult.KNOCKED_OFF));
@@ -403,4 +403,9 @@ spitroast.addUnit()
     .setAggressor(Person)
     .setTarget(OrcDebugger)
     .addMarker(AdaptiveDifferential.FULLYADAPTIVE(AIRules.resultRetaliate, AIRules.resultHostile, AIRules.resultNotHostile))
-    .addMarker(AdaptiveDifferential.FULLYADAPTIVE(AIRules.actionMin, AIRules.actionMed, AIRules.actionMax));
+    .addMarker(AdaptiveDifferential.FULLYADAPTIVE(AIRules.actionMin, AIRules.actionMed, AIRules.actionMax));
+
+
+let outsideRoom = new Room("Outside Room");
+window['outsideRoom'] = outsideRoom;
+window['player'] = WorldState.player;

文件差異過大導致無法顯示
+ 0 - 1
dist/The Obelisk.html


部分文件因文件數量過多而無法顯示