World Map Structures

# Modulus Widget

Convert a World r,q
to a 3x9 Tessellation
rTemplate, qTemplate






Result

# Cells

Tessellation Cells

0, 0 City Tier 1 Elixir Marble Crystal
0, 1 Planks Filler
0, 2 Steel Boost
0, 3 City Tier 1 MDust Steel Scrolls
0, 4 Marble Filler
0, 5 Planks Boost
0, 6 City Tier 1 Gems Planks Silk
0, 7 Steel Filler
0, 8 Marble Boost
0, 9 Belongs to downstairs neighbor

1, 0 Crystal Boost
1, 1 City Tier 1 Steel Crystal Elixir
1, 2 Silk Filler
1, 3 Scrolls Boost
1, 4 City Tier 1 Planks Scrolls MDust
1, 5 Crystal Filler
1, 6 Silk Boost
1, 7 City Tier 1 Marble Silk Gems
1, 8 Scrolls Filler
1, 9 Belongs to downstairs neighbor

2, 0 Belongs to upstairs neighbor
2, 1 MDust Filler
2, 2 Elixir Boost
2, 3 City Tier 1 Scrolls Elixir Steel
2, 4 Gems Filler
2, 5 MDust Boost
2, 6 City Tier 1 Silk MDust Planks
2, 7 Elixir Filler
2, 8 Gems Boost
2, 9 City Tier 1 Crystal  Gems   Marble

# Flying Ducks

Tessellation

The basic building block for the World Map is a staggered 9x3 parallelogram that contains:

  • 9 Cities

  • 9 Resources, each listed twice

  • Staggered and repeated over and over and over again

Tessellation isn’t the sort of thing that one can describe with words, but it’s visually obvious.

# Template Span

rTemplate = Mod( r, 3)
qTemplate = Mod(q,10)

Because the flat topped hexagonal cells zig-zag vertically, horizontal even/odd pairs will have the same vertical index value, although they “look like” they’re off by half a cell.

The (r.q) indexes for the top and bott0m three cells in the tessellated parallelogram group are:

  • (0,0) City

  • (1,0) Crystal

  • (2,1) Magic Dust

  • thru

  • (0,8) Marble

  • (1,8) Scrolls

  • (2,9) City

# Browser Console

Browser Console

Your desktop browser has a Developer Tool that allows you to look at the underlying code that controls what you see on your screen. In particular, we can use it to look at the attributes of the various elements on the world map.

In-Game, get ready to use your World Map Icon, which will land on your city when the map opens.

  • Now press Ctrl+Shift+I or

  • Menu > More Tools > Developer Tools

Now set up your Browser Console environment for looking at cells on the Elvenar World Map.

  • Network Tab

  • Record (Red Circle Square for top window)

  • Filter for json (Funnel and enter json)

  • Search for Your Name (Magnifier and Search Sidebar, which may need to be a bit wider.)

  • Clear the existing data (BOTH Circle Bars)

Now click on your World Map Icon and chase down the r and q values that we will soon plug into the above rqConvert widget.

Then drag the World Map over to an UNDISCOVERED area, plug in the new search Name, and click on their city. Lo and Behold! A neat list of Building Locations!!

But Alas! It’s too good to be true. You can’t get at the data if there’s a lot of it, because the Developer Tools only expect to see a few API calls at a time, and manages the Browser Cache accordingly.

  • Your own city

  • Other cities in your discovered Neighborhood

  • Other cities in your Fellowship

  • Other cities that have a current contribution to one of your AWs

  • And probably some more stuff

We’ll eventually isolate the API calls that are related to Building Location, but it’s a low priority task because the In game Move display with the buildings flattened, and the similar display on Elven Architect make it easy to hunt for a building.

An in-game solution, similar to the Summons widget that we already have for Teleported and Awarded buildings, would be VERY nice and would make a LOT of sense as a “click on my building” tab for the Builder’s Hut.

Developer Mode allows you to do a lot of things on the fly, for troubleshooting. In the Browser Console (the lower window) try typing:
———-> console.log(“Hello World!”)
followed by a semi-colon and Enter.

Once you've set up your Developer Environment, and have poked around a bit, open a new tab for ElvenPathways.com/worldmap

Now drag the tabs to show both the Modulus widget and the Browser Console for the game in a split window, and start converting coordinates. Hooray!

# Production

Squarespace, as is typical of most hosting sites, requires all of the 
"Behind the Curtain" JavaScript code to be placed in a special repository. 
What you're seeing, when a page is rendered, is HTML lipstick.
The bones and muscles are JanaScript or some other advanced language.

// <script>  // Not really though - this text is HUMAN readable (sort of)
// We'd encourage you to read through this code block,
// and buff your JavaScript skills. Pay particular attention to the 
// nested switch code that describes all 3*9+3 = 30 cells in the Template.

/* The following chunk of code has been commented out to
avoid contamination of the JavaScript repository.
{script}
// Here's the actual JavaScript code for Elvenar, that's called by the Submit button,
// or by using   Console.log(rqConvert(r,q));   with your own numbers.
let   r  =  -6;                    // Elvenar Global Horizontal_Index
let   q  = -11;                    // Elvenar Global Vertical_Index 
function rqConvert(r,q) {          // Find the Template coordinates
       const rModulus    =  3;     // The horizontal span of the Template
       const qModulus    = 10;     // The   vertical span of the Template
       let   rTemplate  =  0;     // Maps onto the 0,0 Template (for r = -6)
       let   qTemplate  =  9;     // Maps onto the 0,0 Template (for q = -11)
       let   rqMap= "Result";     // The new results for the Template cell
       const rqMapReturn = document.getElementById("rqMapReturn");
                        // Which is where we will actually display the results     
       
        // Calculate the Modulus Remainder for r and q
        console.log(r + "," + q + " is the World Coordinate");
        rTemplate = ((r % rModulus) + rModulus) % rModulus;
        qTemplate = ((q % qModulus) + qModulus) % qModulus;
        console.log(" " + rTemplate + ", " + qTemplate + " is the Template Coordinate");
        
        // switch looks up the related description
        switch(rTemplate) {           //  r    index for the row
                case 0:               
                switch(qTemplate) {   //     q index for the column
                        case 0: rqMap = " 0, 0 City Tier 1 Elixir  Marble   Crystal"; break;
                        case 1: rqMap = " 0, 1 Planks              Filler          "; break;
                        case 2: rqMap = " 0, 2 Steel               Boost           "; break;
                        case 3: rqMap = " 0, 3 City Tier 1 MDust   Steel    Scrolls"; break;
                        case 4: rqMap = " 0, 4 Marble              Filler          "; break;
                        case 5: rqMap = " 0, 5 Planks              Boost           "; break;
                        case 6: rqMap = " 0, 6 City Tier 1 Gems    Planks   Silk   "; break;
                        case 7: rqMap = " 0, 7 Steel               Filler          "; break;
                        case 8: rqMap = " 0, 8 Marble              Boost           "; break;
                        case 9: rqMap = " 0, 9 Belongs to downstairs neighbor      "; break;
                       default: rqMap = " 0, q Default  shouldn't ever happen      "; break;
                }                                                                   ; break;
                case 1: 
                switch(qTemplate) {      
                        case 0: rqMap = " 1, 0 Crystal             Boost           "; break;
                        case 1: rqMap = " 1, 1 City Tier 1 Steel   Crystal  Elixir "; break;
                        case 2: rqMap = " 1, 2 Silk                Filler          "; break;
                        case 3: rqMap = " 1, 3 Scrolls             Boost           "; break;
                        case 4: rqMap = " 1, 4 City Tier 1 Planks  Scrolls  MDust  "; break;
                        case 5: rqMap = " 1, 5 Crystal             Filler          "; break;
                        case 6: rqMap = " 1, 6 Silk                Boost           "; break;
                        case 7: rqMap = " 1, 7 City Tier 1 Marble  Silk     Gems   "; break;
                        case 8: rqMap = " 1, 8 Scrolls             Filler          "; break;
                        case 9: rqMap = " 1, 9 Belongs to downstairs neighbor      "; break;
                       default: rqMap = " 1, q Default  shouldn't ever happen      "; break;
                }                                                                   ; break;
                case 2: 
                switch(qTemplate) {
                        case 0: rqMap = " 2, 0 Belongs to upstairs neighbor        "; break;
                        case 1: rqMap = " 2, 1 MDust                Filler         "; break;
                        case 2: rqMap = " 2, 2 Elixir               Boost          "; break;
                        case 3: rqMap = " 2, 3 City Tier 1 Scrolls  Elixir   Steel "; break;
                        case 4: rqMap = " 2, 4 Gems                 Filler         "; break;
                        case 5: rqMap = " 2, 5 MDust                Boost          "; break;
                        case 6: rqMap = " 2, 6 City Tier 1 Silk     Dust     Planks"; break;
                        case 7: rqMap = " 2, 7 Elixir               Filler         "; break;
                        case 8: rqMap = " 2, 8 Gems                 Boost          "; break;
                        case 9: rqMap = " 2, 9 City Tier 1 Crystal  Gems     Marble"; break;
                       default: rqMap = " 2, q Default should never happen         "; break;
                }                                                                   ; break;     
                case 3:         rqMap = " 3, q Doesn't exist                       "; break;
               default:         rqMap = " r, q Default should never happen";    // NO break;
        };      
// Push the results to the console
        console.log(rqMap);
// Push the results to the HTML page
        rqMapReturn.innerHTML = rqMap;
}  
// End of the rqConvert() function
</script>
*/

Production JavaScript

# Discovered Neighbors

In the World Map widget on the Desktop version of Elvenar, there’s a very handy list of your Neighbors. If you go total geek, you can use the Chrome Developer tools to trace the list of Neighbors, and you’ll find that the sequence exactly matches the sketch of the Manhattan Distance spiral.

The spiral is used for Immigration, Relocation, Scouting Costs, Provincial Difficulty, and Tournament sequencing, so it’s important, but fortunately there are a lot of well designed popups that do a nice job of guiding your attention, so a vague awareness of the structural details is all that you really need.

The Elvenar Wiki discusses the World map at https://en.wiki.elvenar.com/index.php?title=World_Map#The_World_Map, but the information that’s presented is handwavish. While concentric rings are easy to explain, the devil is in the details. The world map actually uses Manhattan Distances (Taxicab distance) = ( |r|+|q| ). The basic idea is that you have to use the streets. You can’t ignore the terrain.

# Manhattan Distances

# Exercises

Here are some simple JavaScript
exercises that will actually work
in the Chrome Browser Console 
(Ctrl+Shift+I) but, if you're
the slightest bit interested in 
programming, there's a starting 
point that's a lot more fun.
>> codeSwing by Jonathan Carter <<
Click on the link in the Page Footer.

// Exercise #1
// Hello World! is the traditional 
// introduction to any new 
// programming enviornment.
console.log("Hello World!");

// Exercise #2
/* ----------------------------------
Copy Paste or Type these code 
fragments into the Browser Console
now, and once again after you've 
completed the rest of the exercises.
Better yet, just use use codeSwing.

JavaScript is case sensitive and 
weakly typed. Use camelCase for 
naming, and use the Strict ===
Equality Operator when things
look right, but won't work.

At the end of each statement you 
need either a semicolon or Enter.
Get in habit of including the ;

Your first pass will have several
errors, because the functions and
global variables have not yet been
defined. This is, by the way, a VERY
common programming problem, so pay 
attention to the various error flags.
-----------------------------------*/
<script>
console.log("Hello World!");   // 2a

baProduct = null;              // 2b
console.log(baProduct(6, 10)); // 2b
 
g = 234;              //      234 2c                        // 2c 
f = "234";            //    '234' 2c                        // 2c 
g === f;              //    false 2c
g == f;               //     true 2c
g = f;                //    '234' 2c
g;                    //    '234' 2c
f;                    //    '234' 2c
g = +f;               //      234 2c
f;                    //    '234' 2c 
g = ++f;              //      235 2c
f;                    //      235 2c
g = ++f               //      236 2c
f;                    //      236 2c
f = "234" + "567";    // '234567' 2c
g = +f;               //   234567 2c
</script>                       

// Exercise #3
// Return the product of a and b
<script>
function baProduct( b, a) {    
         return b * a;
};
console.log(baProduct(6, 10));  
// Or plug in your own numbers
</script>

/* Exercise #4
A simple Hello World function, using
global variables. The reason for the 
goofy reverse order, rather than 
the usual a,b,c  i,j,k  q,r,s  x,y,z
order, is because the programmers 
were thinking (Row,Column), 
for switching convenience on the 
World Map, and they continued listing
it that way in the Elvenar code.

But at least the City Buildings use 
the normal x,y convention, 
although those files are obscured 
most of the time.
*/ 
<script>
i = "Hello World! ";
h = 16; // This is a GotCha
        // The Result will be 15
g =  5;
f = 10;
// The console is a very primitive 
// editor, so enter the entire
// function without pressing Enter 
function simple(g,f) {            
console.log("A simple function"); 
   h = f + g;
   return i + " " + h + " times over.";
};  
simple(g,f);  
// Or plug in your own numbers

// Exercise 5
/* 
Are you up to a 
Programming Challenge?
1. Pick any three digit number
2. Concatinate (NOT add) 
   it to itself, so 345345,
   to obtain a 6 digit number
3. Divide the number by  7
4. Divide the result by 11
5. Divide the result by 13
6. Your original number???  
   Strange, huh?
   Fun with Primes :-}
*/

JavaScript Exercises

# Innogames on GitHub

Innogames on GitHub

Innogames has published a LOT of code on GitHub. They have 132 different repositories for your enjoyment.