? Show All Error writing cache file
I
should respect transition ticks, i.e. gradually open the shroud during moveHero 
#mmpso I
partial shroud currently reveals presence of objects like border guard, hero, boat (albeit not their ownership thanks to grayscale being applied); but they can't be simply hidden (like DOM.Map does) because map.miniMap stores info about either the impassable object or the terrain so if we hide the object we don't know what type of terrain to show; MiniMapTile can be (and should be) changed to store both fields 
I
if (visible >= 0 && this._fogBits) { 
I
add list of AObject->$pending 
I
case 'hasBuilt': // XXX 
I
DOM.Map draws shadows incorrectly: SoD separates shadow from picture while def2png.php combines them. If an object overlaps another, its shadow should be drawn behind the other, not on top of it like it currently happens. This won't be fixed in DOM.Map (as it will double the required number of nodes). 
I
SoD does smooth scroll (not tile-by-tile) - add "mapLockMove" to Screen, set it during transition and manually animate scroll position 
I
// This is technically incorrect but XXX transitions currently don't 
I
should respect transition ticks, i.e. gradually open the shroud during moveHero 
I
proper unhooking 
I
case 'highScores': // XXX 
I
case 'newCampaign': // XXX 
I
//set('quickCombat', false) // XXX 
I
finish localization 
I
not permitted because Worker currently has no means to show GrantModules notifications; also, 3rd party modules may not expect to be run in Worker context without access to DOM 
I
this.do('tacticsEnd') 
I
8 check immunities when estimating targets 
I
8 currently spells are checked in fixed order; they should be examined all together, sorted and best chosen based on damage to SP ratio (e.g. if spell A deals 10 damage and costs 5 SP while B deals 15 damage and costs 10 SP then A is better because for 10 SP during 2 turns we inflict 20 damage, not 15) 
I
currently buying the most suitable creature only; should check all other available creatures and buy multiple during one visit 
I
12 would be good to exchange garrisons directly with heroes (heroTrade) without using town as a relay 
I
Ideally should check aiValue and swap with town's garrison if hero's creature is stronger. 
I
check if guards were already defeated, if yes then set guards=0 
I
tactics for distance from combat field edge (currently only implemented for distance from creature's original position) 
I
options.formation 
I
8 check for obstacles/fortifications along the trajectory 
I
4 support SoD help bar here and in all other windows/screens 
#mmrl I
morale, luck (sign() in classic), atk/def/knw/spp ("+# Defense [Skill]"), skill ("Advanced Wisdom"), spell 
I
that's still a problem if a party is removed mid-combat (e.g. due to fleeing); we don't have this feature yet so not addressing it Also not clearing _animateHero timers because that method is playing cheers animation in non-classic mode upon combat end. 
I
aborting doesn't work well ATM (at least on combatMove), likely due to improper handling of transitions abort 
I
2 even though mode is disabled while transitions are pending, bottom panel buttons are currently kept enabled 
I
// Barely adequate (XXX) preloading. Without this animations even with local server are horrid. 
I
show total "(hp)" of top stack in nonclassic mode 
I
currently affectors are not updated within a transition 
I
Lower and mid-lower walls should use a kind of "inverse Z": unlike normal order, they overlay creatures standing on the right of them and underlay those on the left. This troublesome exception isn't implemented currently except for lower wall that overlays creatures both on the right (good) and left (bad). 
I
outlines of activeTurn and hover must be pulsating like in SoD 
I
shooter must turn before and after shooting if target is on the left (like in combatMove) 
I
add shootingCloud effect at this point and wait for completion before continuing execution below (+ DEATHCLD sfx) 
I
for better effect unlock/parallel should happen in impact's climax frame (some point in the middle of playing it), not immediately 
I
update Z index during move (not so trivial for flying) 
I
44 It appears making perfect move animation requires too much time so using quick and dirty method for now: force 70 ms per walk frame and 0.1 second per moved cell, then adjust movement speed ($.animate()) so that move animation ends on the last frame. SoD is using a more complex and fluent approach which remains to be researched. 
I
when a creature is hit or is dying, it should turn to face the attacker 
I
duration depends on pixels, not the best concept for portability 
I
also highlight cells under creatures that can be healed (in non-classic mode) 
I
if not supported, must additionally reset Screen's speed options to 1.0 on start; while implementing, remember they're not supported in FF <57, not just in IE 
I
implement quick combat/auto combat and enable all Auto-Combat Options checkboxes 
I
add efficiency explanation ("Does X points of damage", "Chances of success are X%", etc.) 
I
when replay playback is implemented, replace the useless Load > Tutorial button with load replay button 
C, I
recheck this and other game screens (ADVMAP, SpellBook, Combat, etc.), add missing hotkeys 
I
playback of replays 
I
not implemented because decompression API is recent (Chrome 80+, no FF) and its compatibility with gzencode() is unknown 
I
storing binary stuff in localStorage is inefficient, IndexedDB is much better and has no quota but the API is troublous 
I
upon monster encounter, replace its image with AVWATTAK.DEF until the combat ends (or possibly replace the image during any active $pending on the monster's AObject) 
I
15 there is currently no way to either cancel message on timeout or bring it up again for user to act (think of event log from AoW), which is a problem if user reloads the page (transitions added before the reload will be dropped, not reprocessed); for now, prefixing most channels here with '!' to ensure cleanup actions are always run (even if after some time, such as when user is in a combat) except if user reloads the page 
#trsr I
15 when saving a game, pending transitions are also saved; they must be picked up when loading and either resumed (if possible) or deleted (if can't resume without data lost at the collect step that happened before load); perhaps add a "resume_..." that fulfills the role of select_... and collect_... for such transitions 
#huic I
these require confirmation to close and confirmation is only possible to non-observer because it involves calling an RPC command; ideally observer should see choices the main player is making by means of a system similar to Tracker 
I
if (this.sc.rpc.get('observer')) { return } 
I
if (this.sc.rpc.get('observer')) { return } 
I
if (this.sc.rpc.get('observer')) { return } 
I
if (this.sc.rpc.get('observer')) { return } 
I
SoD also allows building ships on owned shipyard by merely clicking on it rather than encountering 
I
add aggression info (likely to join, pay so much gold) 
I
this check is not accurate as certain objects (e.g. Warrior's Tomb, banks) do not disclose fulfillment status until encountered; perhaps add a selector to quest_fulfilled target like ifPeeking that will allow the object determine when it's being previewed and when it's encountered 
I
Kingdom Overview 
I
// SoD doesn't permit disembarking on top of an Event (which is the only ground object with passable actionable spot) but allows on top of Grail (which is hidden in HeroWO and ignored by pathfinder, cursor, spot effects, etc.). Currently this disembarking rule is an artificial limitation on the side of UI (XXX should be enforced in PathCost). 
I
show growth affectors 
I
auto-cancel windows if building gets deleted 
I
in SoD it only costs gold; show others in the UI too and make it use calc (artifactCost) 
I
for producing buildings and production upgrades SoD shows a different box with the creature's animation, cost and available count 
R, I
review all places where classic is accessed and add listening to change_classic (possibly after/together with #clsi
I
//this.nested('quickCombat').set('checked', this.sc.get('quickCombat')) 
I
//this.nested('subtitles').set('checked', this.sc.get('subtitles')) 
I
determine if replay saving is available; if not, disable, else on click reroute directly to replay saving 
I
This is fine except it allows bypassing Artifact->$slots requirement of not accepting backpack. It's expected that the user has to put the artifact back to some slot eventually, but he can easily avoid this (e.g. by cancelling HeroInfo). It's probably a good idea to forcefully put "in-progress" artifacts back after some timeout, upon change of Player._opt.screen, pending, etc. (but then what to do if another artifact already occupies that slot and that artifact can't fit into backpack either?). 
I
account for garrison_reinforce/reduce 
I
don't allow garrison to consist only of creatures with maxCombats <> false; also update checks in RPC 
I
draw popup 
I
also disable when have no AP to travel first route segment 
I
Pathfinder should take into account target object's passability. However, it is returned by triggerSpotEffects ('stand', 'stop', etc.) which is not known beforehand (and it may depend on arbitrary world properties, moreover - those set after part of the move route was traversed). For example, in SoD placing a Scholar and wearing Angel Wings or Boots of Levitation results in the following move route (¹ to ³): [_²[S³[_] _ = ground, S = scholar [ ¹[ ][ ] water [_][H][_] H = hero Interestingly, placing an actionable spot of some object (like Windmill) on the left of Scholar (in ²) makes the latter unreachable (even though ² itself is reachable and can be triggered as normal travel destination). For this to work, we likely need to move passability detection from triggerSpotEffects into a more specialized, almost constant method. 
I, C
Some diagonal movements (where any adjacent tile is a ground?) are prohibited on water. For example, one cannot interact with Mermaids after boarding [S] here (Mermaids shifted by one to the left are reachable): [_][_][ ][ ] _ = ground [ ][ ][ ][ ] [ ] = water [ ][#][@][#] [#@#] = Mermaids [ ][S][H][_] S = ship, H = hero on ground [ ][ ][_][_] A simpler example where ² is only reachable via ¹: [ ²[_] _ = ground [ ¹[S] 
I
Since a monster prevents movement around itself, it is impossible to encounter the monster's own actionable spot: [ ][.][.][.] [.] = guarded [H][.][@][.] H = hero, @ = monster (unreachable in HeroWO) [ ][.][.][.] However, SoD makes an exception, allowing building route to [@] through any [.] (guarded by target [@] only) if [@] is the travel destination. This purportedly improves user experience even though technically it works exactly as if moving onto a [.] (the hero stops and combat starts without reaching [@]). 
I
14 receiving hero must be adjacent or be garrisoned while other is visiting (same as in do=garrison, see comments there) 
I
14 check Player._opt.screen* 
I
check $pending for both bonus and hero objects; here and in other do_... 
I
implement encounter of standalone tradingPost 
I
allow decisionMaker make a counter-offer with up to +30% difference from the counted price Normally, pendingSurrender cannot be serialized as part of Party because surrenderAsk's Async is part of WS pending until surrenderAccept is called, which unsets pendingSurrender. 
I
add check or Effects for disabling healing Ballista and other artifacts 
I
refresh the others var since _makeDamage() (hooks) could have some side effects on arbitrary creatures 
C, I
looks like in SoD some creatures' cloud (Magog) has friendly fire, some (Lich) doesn't 
#rrl R, I
as it stands now, msg[0] cannot be localized because it joins many targets together: "The ... do ... damage. [Target1 perish] [Target2 perish] ..." 
R, I
SoD has different messages for ripple-type spells: - The Death spell does %d damage \n to all living creatures. - The %s spell does %d damage \n to all undead creatures. - The Armageddon does %d damage. We're using the same message for ripple- and arrow-type spells since HeroWO has a complex system of deciding which creature is hit (livind, undead, etc.), and we also explain how many targets perished. 
I
51 this currently examines slots where the artifact is in, allowing blacklisted artifacts if they're in backpack (e.g. editor allows placing Ballista in Backpack) 
I
this rounding creates a disparity because artifacts are distributed from each hero's pool: suppose there are 3 defeated heroes, each with 10 artifacts, and 3 alive heroes; 3rd alive hero receives 4*3=12 artifacts while others - 3*3=9; if we were to collect all enemy artifacts in a common pool and only then distribute, then every hero would receive the same amount of artifacts (3*10/3=10) 
I
// 3 is used for Pandora's Box. Conditions are matched in order. (*) are not implemented conditions because they are Effects and not tracked by addedBonuses (XXX). 
I
Must ignore guards when the triggered spot effects resulted in the hero not stepping on this spot. This means guards around the entered and exited monoliths are ignored, as are guards when attacking/trading with a hero. As a special exception, water-based guards around the boat are ignored when embarking (but ground guards around the disembarkation spot are not). But, for example, a guarded Lean To can be only interacted after defeating the guards. Currently we ignore guards when there's anything that will be acted upon except actionable without impassable (Event). UI cursor detection should be updated too. 
C, I
which monster of multiple guards is chosen? with max object ID (closest to right-bottom map corner)? 
I
newly built building should also trigger its encounter, immediately 
I
SoD has special behaviour when defending a town with visiting hero but none garrisoned: it combines garrisons of town and hero; if there are more different creatures then slots then some algorithm is used to leave certain town creatures in town, i.e. omit from combat; if defender wins, those extra creatures remain in town intact; if he loses, they are removed (town's garrison is cleared upon defeat); we currently don't do any of this - if the hero loses, the attacker will have to attack the town's garrison next (both combats happen with fortifications) 
I
38 altarOfSacrifice 
I
38 blackMarket 
I
38 denOfThieves 
I
38 freelancerGuild 
I
38 hillFort 
I
38 obelisk 
I
38 refugeeCamp 
I
38 sirens 
I
38 tradingPost 
I
38 university 
I
pathfinder should regard a fulfilled borderGate as fully passable (even though cursor shows it's interactive it does nothing) 
#mof I
implement monster fleeing 
I
//['retreatCan', true, 'ifObjectType' => array_search('monster', AObject::type)], 
I
0 25%/50%/100% of creatures normally fleeing from your army offer to join 
I
0 Some creatures will ask for money for joining, but most of them will not, especially if they are weak enough. 
I
//> retreatCan bool `- possibility for fleeing, for combat hero >>and for ADVMAP monster (XXX) before combat (this happens after check for 'creature_join')<< (XXX rename target for this case) 
I
//$this->effect(['retreatCan', $this->o_false, 'ifObject' => $obj->id]); 
I
new hero object should respect quest removal transition (currently prison disappears when actor moves to it but new hero appears immediately, before that) 
I
count should be a word: "few", "several", etc. (XXX respecting garrisonSee?) 
I, C
67 SoD updates state of heroes at the beginning of their turn rather than the day. example: have P1, P2; P1's turn is before P2; do P2's spellpoints regen when P1 starts turn or this happens only after P1 ends turn and P2's turn starts? 
I, C
67 same for timed events: they must occur at the beginning of turn (in non-simultaneous/classic turn mode), not daybreak 
I
update duration 
I
support hero placeholders 
I
update duration 
I
this works if initial experience is < level 2; if not, SoD does some kind of (XXX random-based?) "unattended level-up" (automatically choosing stats and skills); at very least, $level should be bumped here 
I
Determines if hero's encounter with this object will be allowed to produce bonuses. This is currently used to check if a Windmill was visited this week, if Border Guard can be passed, etc. but it has several issues, like revealing info that the player shouldn't see until he carries the visit - like if a Shipwreck has been already sacked. 
I
SoD shows messages for both bonus buildings and available (but make sure to not show message for buildings created as a result of Random town initialization in h3m2herowo.php) 
I
currently we're pushing creatures to hero's garrison until it's full; the remainder is lost; implement SoD's exchange dialog (GARRISON) - but only for some encounters (like bank reward), not others (like 1-st level dwellings) 
I
granting during handleInitiallyOwned should be "non-interactive" (no transitions) 
I
should appear before levelup Messages are processed in the end, once all addedBonuses were filled. 
I
turnLength: 0, // XXX 
#mstr I
rather than serializing no transitions, we should serialize those with unset collect (not yet selected); also, perhaps skipTransitions is unnecessary at all, and that all transitions should be serialized in all cases to allow the client to resume some of them (trsr
I
This implementation supports pathfinding within the same Z only. 
I
3 require giving hero to be controller by current player but allow receiving hero to be anyone - except for 'swap' where both heroes must be controlled 
I
3 check spatial relations of receiver/giver (if both are heroes - they must be adjacent, if one is town - another (hero) must be garrisoned or visiting) 
I
3 check Player._opt.screen* 
I
6 add checks 
I
6 check that hero being entered/left and town are not $pending 
I
Add more features, such as: add switching buttons on the right panel of ADVMAP (a button per observable player - neutral observer = all players, others = players in their team). All buttons are in one group and only 0 or 1 in the group must be pressed; if all are off then automatic following of the player's screen is disabled, if 1 then restore() is called. 
I
mapHideEnemy: false, // during enemy turn hides ADVMAP (shows fog of war everywhere) and shows shield in place of minimap, even when enemy moves in places explored by the player (makes mapEnemySpeed ineffective) 
I
$(document) // XXX no off() 
I
public $maxLevel; // 0/null/false unlimited XXX 
I
// There may be multiple `'``> lines with the same object type if the type is further split into subtypes (for example, `'hero is the type but a property may have different sets of value types for regular heroes and random heroes). Currently (XXX) typesets of all object type's lines are internally merged into one so it doesn't make a difference, but in the future the schema generation algorithm may be improved to account for subtypes and generate more compact schemas. For example, if regular hero uses property `'$A but not `'$B while random hero uses `'$B but not `'$A - current algorithm allocates separate slots for `'hero object type for both `'$A and `'$B, instead of placing them on the same slot. 
I
refugeeCamp - must reset each Monday 
I
public $patrol; // XXX 
I
`> hero ditto `- as `'dwelling; not implemented (XXX
I
need to use certain Effect priority/stack to clear only creatures' immunities and keep immunities like those of Sphere of Permanence 
I
// Angelic Alliance XXX 
I
// Cloak of the Undead King XXX 
I
// Elixir of Life XXX 
I
// Titan's Thunder XXX 
#hoshi I
when it's on, SoD seems to maintain two AP values: one for ship, one for horse; when dis/embarking, it just swaps the two so that after embark you get a lot of APs and if you immediately disembark, you get the same amount of land APs as before; or, if the artifact's description is right, the game maintains one AP value but "converts" between them when dis/embarking 
#grl I
grail buildings: TOCS/TOF/...+HOLY except: TOFHLYAA TONHOLYA TOSHOLYA TOTHOLYA; icons: BOEGRAIL BOFGRAIL BONHOLYG BOTGRAIL 
I
create new grail object and place it anywhere if got no premade object, provided there is any obelisk object 
I
//buildings.push(self.grailBuildings) 
I
with Aurora Borealis, replace all spells' icons with SPELLSCR.DEF frame 70 
I
//array_fill_keys($c_grail, [XXX), 
I
'skyship' => 13, // XXX 
I
hallFrame 20 if with ship, also different outline (TOELBOAT) 
#dbst I
there also exists BOCSCV2S.BMP and it's likely an $icon version used when trainingGroundsU is present but I dunno where BO* appear in SoD so can't check that, plus we don't have $iconU 
I
$icon variants exist: BORDWF1T BORDWF1H BORDWF1B BORDWF1 BORDWF2T BORDWF2H BORDWF2B BORDWF2 
I
$icon variant exists: BOSMRK2C 
I
'mysticPond' => [ 
I
'treasury' => [ 
I
'castleGate' => [ 
I
'skeletonTransformer' => [ 
I
'portalOfSummoning' => [ 
I
'freelancerGuild' => [ 
I
'ballistaYard' => [ 
I
'magicUniversity' => [ 
I
in SoD is using a beam attack 
I
in SoD is using a beam attack 
I
new spells provided or existing spells overridden by the map are ignored because databank spells are hardcoded; same issue in defining object effects (Corpse), etc. 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I
// 20% chance for both spells. XXX 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I
// 10% chance. XXX 
I
// 20% chance. XXX 
I
// 20% chance. XXX 
I, ID
Unknown chance. 
I, ID
Unknown chance. 
I
// 20% chance. XXX 
I
Implement extra skill (Rebirth). 
I
Implement extra skill (drains spellpoints). 
I
Implement extra skill (Fire Shield). 
I
"channel 20% of spell points spent by enemy spellcasters directly into their hero’s spell point pool". 
I
hide these from H3.DOM.Combat.Queue 
#twm I
tower's fortification must be land mines placed along the walls, doing 150 damage but only once per spot/mine per combat; this should be implemented after spells like land mines and quicksand are implemented 
I
//$siegeObstacles[] = ["SG{$s}MOAT", $bmp, $c_moat, ${"g_$town"}, 0, 0, 1, 1, '1']; 
I
4 Angel Wings affects path cost 
I
//array_fill_keys($c_altarofSacrifice, [XXX]), 
I
//array_fill_keys($c_blackMarket, [XXX]), 
#dlc I
the replaced substring is not found in localized TXTs 
I
str_replace('1000 gold', '`{Checks`}', toMarkup($adve[73], '`{Audio FAERIE`}')), 
I
str_replace('1500 gold', '`{Bonuses`}', toMarkup($adve[118], '`{BonusesImages`}`{Audio CHEST`}')), 
I
str_replace('2000 gold', '`{Checks`}', toMarkup($adve[150], '`{Audio GAZEBO`}')), 
I
38 str_replace("the '%s'", '`{Bonuses`}', toMarkup($adve[155], '`{BonusesImages`}`{Audio GENIE`}')), 
I
str_replace('1000 gold', '`{Checks`}', toMarkup($adve[160], '`{Audio MILITARY`}')), 
I
//array_fill_keys($c_hillFort, [XXX]), 
#eyom I
SoD also shows every Eye, pausing for several seconds before going to next; we should do the same, plus allow breaking out of this by clicking anywhere (in non-classic mode) 
I
//array_fill_keys($c_marketOfTime, [XXX]), 
I
//array_fill_keys($c_obelisk, [XXX]), 
C, I
SoD sometimes (randomly?) adds quests to some artifact objects (have Wisdom, have Leadership, have gold, have gold and precious resource, etc(?)); this needs research randomArtifact: Places a random artifact on the Adventure Map. Artifact can be any class. Grail is excluded. randomTreasureArtifact: Places a random Treasure class artifact on the Adventure Map. randomMinorArtifact: Places a random Minor class artifact on the Adventure Map. randomMajorArtifact: Places a random Major class artifact on the Adventure Map. randomRelic: Places a random Relic class artifact on the Adventure Map. spellScroll: This scroll contains a spell, which is added into a hero’s spell book for as long as you carry the scroll. I think I've seen another (unused?) class for spell scroll somewhere. At least the editor's help has this second entry: 01 spell per scroll. Appears in hero's spell book if artifact is equipped. 
I
instead of modal message show it in the right-side panel 
I
//array_fill_keys($c_refugeeCamp, [XXX]), 
#sclr C
22 what happens if hero has no room for more secondary skills? 
I
22 a cap on the number of secondary skills should be enforced like in SoD 
#sclr I
22 SoD never chooses a spell bonus if hero's no book 
I
22 a cap on the number of secondary skills should be enforced like in SoD 
I
spells are not handled by Bonuses/Images 
I
//array_fill_keys($c_sirens, [XXX]), 
#stcv I
upgrade cavaliers 
I
//array_fill_keys($c_denOfThieves, [XXX]), 
I
//array_fill_keys($c_tradingPost, [XXX]), 
I
35 the message should appear before LevelUp window 
I
//array_fill_keys($c_university, [XXX]), 
I
//array_fill_keys($c_freelancerGuild, [XXX]), 
I
//array_fill_keys($c_heroPlaceholder, [XXX]), 
I
45 a visit to already owned mine allows leaving garrison (for abandoned too) 
I
add growth effect in towns for these creatures whileOwned, and to their upgraded forms 
I
must use custom animation (polyline) 
I
custom animation (red overlay fade-in-out) 
I
custom animation (fade-out) 
I
custom animation (fade-in) 
I
custom animation (fade-in) 
I
custom animation (fade-in) 
I
custom animation (fade-in) 
#sssl I
H3.Rules is calculating creature_attack and other creature_... stat targets without respect to who is being attacked 
#sscs I
this must increment the recurring Garrison->retaliating so that target may retaliate again this turn 
I
$ifVisiting may be also set to the hero that visits a garrison (gates). 
I
//> spellMastery `- if casting by creature XXX creature casting 
I
//> artifactChance `- if buying from Artifact Merchant XXX 
I
//> creature_hordeGrowth int `- not currently used (horde world bonus = double creature_growth) XXX 
I
//> retreatCan bool `- possibility for fleeing, for combat hero >>and for ADVMAP monster (XXX) before combat (this happens after check for 'creature_join')<< (XXX rename target for this case) 
I
//> creature_join int % multiplier `- chance whether monster group will join hero on encounter (XXX
I, R
// Archers to Sharpshooters, etc. (XXX also merge with creature_upgradeCan?) 
I
//> creature_reanimate int `- number of new creatures to create after combat (XXX
I
{Checks} only works for existing objects; it will fail when hero/monster was defeated 
I
Must remove Lighthouse and Shipyard if the town is not near water (SoD allows them but factually ignores "Built" state for these two in Town Properties). XXX However, this likely has to be done on the JS side because this has to apply to Timed Event buildings as well. 
I
//0x1D => 'CHR', // XXX 
I
//0x33 => 'WoG', // XXX 
I
//0xF0 => 'VCMI', // XXX 
I
throw new CliError('Converting from JSON (-ij) is not implemented yet.'); // XXX 
I
protected function collectStatistics(H3M $h3m, array &$stats) { 
I
protected function printStatistics(array &$stats) { 
I
in SoD width depends on amount of content; also need to add scrollbar if content is too long */ 
I
<!-- SoD allows customizing difficulty mode without opening Advanced Options. XXX --> 
I
On (not implemented) <!--XXX-->