Advertisement
Bisqwit

My solution to Elevator Saga

Jan 24th, 2015
1,868
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {
  2.     /* This is my (Joel Yliluoma's) solution to Elevator Saga at http://play.elevatorsaga.com/ */
  3.     /* This code plows through all challenges from #1 to #17. However, note:
  4.      * In challenge #6, you need to change one of the for-loops, below. (Indicated in comments.)
  5.      * In the max-wait challenges, you may need to click Restart a few ones to get better luck.
  6.      */
  7.     /* Check out my programming-related YouTube channel! http://youtube.com/user/Bisqwit */
  8.    
  9.     init: function(elevators, floors) {
  10.         var bot=999, top=-1, upOrder={}, dnOrder={}, age={}, totalage=1;
  11.        
  12.         floors.forEach(function(f) {
  13.             var fn = f.floorNum();
  14.             // Find top and bottom floors
  15.             if(fn > top) top = fn;
  16.             if(fn < bot) bot = fn;
  17.             f.on("up_button_pressed",   function() { upOrder[fn] = fn; } );
  18.             f.on("down_button_pressed", function() { dnOrder[fn] = fn; } );
  19.             age[fn] = 0;
  20.         });
  21.  
  22.         //elevators.pop(); // Uncomment for challenge #6
  23.         elevators.forEach(function(e) {
  24.             var curdir=0;
  25.             e.goingUpIndicator(true);
  26.             e.goingDownIndicator(true);
  27.             e.pOrder = {};
  28.             // goTo: Register a new target
  29.             e.goTo  = function(f, now) {
  30.                 var cur = e.currentFloor();
  31.                 //console.log("goto " + f, pOrder,dnOrder,upOrder);
  32.                 if(f != cur) { if(f < cur) curdir=-1; else curdir=1; }
  33.                 e.goToFloor(f, now);
  34.                 // There's a promise we will go to this floor, so delete it
  35.                 delete e.pOrder[f];
  36.                 delete upOrder[f];
  37.                 delete dnOrder[f];
  38.             };
  39.             e.on("floor_button_pressed", function(num){ e.pOrder[num]=num; });
  40.             e.on("passing_floor", function(f,dir) {
  41.                 if(e.pOrder[f] || (e.loadFactor() < 0.3 && (
  42.                                   (/*dir=="up" &&*/ upOrder[f])
  43.                                || (/*dir=="down" &&*/ dnOrder[f]) )))
  44.                 {
  45.                     e.goTo(f, true);
  46.                 }
  47.             });
  48.             e.on("stopped_at_floor", function(f) {
  49.                 // Are we at top floor? We are going down next.
  50.                 var cur = e.currentFloor();
  51.                 if(cur == top) curdir = -1;
  52.                 if(cur == bot) curdir = 1;
  53.                 // We have arrived at this floor.
  54.                 age[f] = ++totalage;
  55.             });
  56.             e.on("idle", function(){
  57.                 var cur = e.currentFloor(),  bestscore=top*2, target = -1;//Math.floor(Math.random() * (top+1));
  58.                 //console.log("cur="+cur, pOrder);
  59.                 // Pick a target. Check each floor first.
  60.                 var orders = [e.pOrder,upOrder,dnOrder];
  61.                 if(e.loadFactor() >= 0.02) orders = [e.pOrder]; // too full
  62.                 for(var oi in orders) for(var order in orders[oi])
  63.                 {
  64.                     if(order == cur) { continue; } // Ignore requests to go to the same floor...
  65.                     // The score (really penalty) is the distance to the current floor
  66.                     var score = Math.abs(order - cur) + (age[order]-totalage);
  67.                     //if(curdir != 0 && (curdir > 0) != (order > cur)) score += totalage; // Orders to change direction are ranked low
  68.                    
  69.                     // If we don't have any passengers, downrank floors that _other_ elevators are heading towards
  70.                     if(e.pOrder.length == 0)
  71.                         for(var ei in elevators)
  72.                             if(elevators[ei].pOrder[order])
  73.                             {
  74.                                 // What is the probility the other elevator will head to this floor _next_?
  75.                                 var unprob = Math.abs(order - elevators[ei].currentFloor()) + elevators[ei].pOrder.length;
  76.                                 score += top/unprob;
  77.                             }
  78.                    
  79.                     if(score < bestscore) { bestscore=score; target=order; }
  80.                 }
  81.                 // Now get the highest ranking candidate, and honor it.
  82.                 if(target == -1) { e.goTo(cur, true); return; } // This will just re-launch the "idle" code
  83.                 /* There is one special case that needs to be worked on.
  84.                  * Suppose one elevator is empty and decides to go
  85.                  * towards a floor to pick up passengers (based on upOrder/dnOrder).
  86.                  * Now there's another elevator that has passengers who want to leave
  87.                  * at that same floor (its pOrder), but he's still busy heading to another floor.
  88.                  * There's a high chance both elevators will rush to the same floor at the same time.
  89.                  */
  90.                 e.goTo(target);
  91.             });
  92.         });
  93.     },
  94.     update: function(dt, elevators, floors) {
  95.         // We normally don't need to do anything here
  96.     }
  97. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement