diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee
index e5da46c50..632302f63 100644
--- a/app/lib/surface/SpriteBoss.coffee
+++ b/app/lib/surface/SpriteBoss.coffee
@@ -163,7 +163,8 @@ module.exports = class SpriteBoss extends CocoClass
       if sprite = @sprites[thang.id]
         sprite.setThang thang  # make sure Sprite has latest Thang
       else
-        sprite = @addThangToSprites(thang) or updateOrder
+        sprite = @addThangToSprites(thang)
+        Backbone.Mediator.publish 'surface:new-thang-added', thang:thang, sprite:sprite
         updateCache = updateCache or sprite.displayObject.parent is @spriteLayers["Obstacle"]
         sprite.playSounds()
     for thangID, sprite of @sprites
diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index d600444e1..c2303cc77 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -124,16 +124,15 @@ module.exports.thangNames = thangNames =
     "Skoggen"
     "Treg"
     "Goreball"
-    "Shmeal"
     "Gert"
     "Thabt"
-    "Iyert"
-    "Palt"
     "Snortt"
     "Kog"
   ]
   "Ogre Munchkin F": [
-    
+    "Iyert"
+    "Palt"
+    "Shmeal"
   ]
   "Ogre M": [
     "Krogg"
@@ -144,12 +143,11 @@ module.exports.thangNames = thangNames =
     "Mak Fod"
     "Trung"
     "Axe Ox"
+  ]
+  "Ogre F": [
     "Nareng"
     "Morthrug"
     "Glonc"
-  ]
-  "Ogre F": [
-    
   ]
   "Ogre Brawler": [
     "Grul'thock"
diff --git a/app/lib/world/rand.coffee b/app/lib/world/rand.coffee
index dc6102a4e..0def76c4c 100644
--- a/app/lib/world/rand.coffee
+++ b/app/lib/world/rand.coffee
@@ -32,8 +32,4 @@ class Rand
   rand2: (min, max) =>
     min + @rand max - min
 
-  # return an array of numbers from 0 to n-1, shuffled
-  randArray: (n) =>
-    _.shuffle [0...n]
-
 module.exports = Rand
\ No newline at end of file
diff --git a/app/lib/world/thang.coffee b/app/lib/world/thang.coffee
index b36a5c6d2..b8097283b 100644
--- a/app/lib/world/thang.coffee
+++ b/app/lib/world/thang.coffee
@@ -4,44 +4,29 @@ ThangState = require './thang_state'
 Rand = require './rand'
 
 module.exports = class Thang
-  @className: "Thang"
-  @random = new Rand
+  @className: 'Thang'
+  @remainingThangNames: {}
 
-  # Random ordering for each sprite name
-  @ordering: (spriteName) ->
-    Thang.orders ?= {}
-    names = thangNames[spriteName]
-    if names
-      len = names.length
-      array = Thang.orders[spriteName]
-      unless array?
-        array = @random.randArray len
-        Thang.orders[spriteName] = array
-    else
-      array = []
-    array
-
-  @nextID: (spriteName) ->
+  @nextID: (spriteName, world) ->
     Thang.lastIDNums ?= {}
-    names = thangNames[spriteName]
-    order = @ordering spriteName
-    if names and names.length
-      lastIDNum = Thang.lastIDNums[spriteName]
-      idNum = (if lastIDNum? then lastIDNum + 1 else 0)
-      Thang.lastIDNums[spriteName] = idNum
-      id = names[order[idNum % names.length]]
-      if idNum >= names.length
-        id += Math.floor(idNum / names.length) + 1
-    else
-      Thang.lastIDNums[spriteName] = if Thang.lastIDNums[spriteName]? then Thang.lastIDNums[spriteName] + 1 else 0
-      id = spriteName + (Thang.lastIDNums[spriteName] or '')
-    id
+    originals = thangNames[spriteName] or [spriteName]
+    remaining = Thang.remainingThangNames[spriteName]
+    remaining = Thang.remainingThangNames[spriteName] = originals.slice() unless remaining?.length
 
-  @resetThangIDs: -> Thang.lastIDNums = {}
+    baseName = remaining.splice(world.rand.rand(remaining.length), 1)[0]
+    i = 0
+    while true
+      name = if i then "#{baseName} #{i}" else baseName
+      extantThang = world.thangMap[name]
+      break unless extantThang
+      i++
+    name
+  
+  @resetThangIDs: -> Thang.remainingThangNames = {}
 
   constructor: (@world, @spriteName, @id) ->
     @spriteName ?= @constructor.className
-    @id ?= @constructor.nextID @spriteName
+    @id ?= @constructor.nextID @spriteName, @world
     @addTrackedProperties ['exists', 'boolean']  # TODO: move into Systems/Components, too?
     #console.log "Generated #{@toString()}."
 
diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index 7935099ec..8f572fb1f 100644
--- a/app/views/editor/level/thangs_tab_view.coffee
+++ b/app/views/editor/level/thangs_tab_view.coffee
@@ -349,7 +349,7 @@ module.exports = class ThangsTabView extends View
     @editThang thangID: id if id
 
   addThang: (thangType, pos) ->
-    thangID = Thang.nextID(thangType.get('name')) until thangID and not @thangsTreema.get "id=#{thangID}"
+    thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
     if @cloneSourceThang
       components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"
       @selectAddThang null
diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/spell.coffee
index 1757ae8c9..113ce23d5 100644
--- a/app/views/play/level/tome/spell.coffee
+++ b/app/views/play/level/tome/spell.coffee
@@ -21,7 +21,7 @@ module.exports = class Spell
     @tabView.render()
 
   addThang: (thang) ->
-    @thangs[thang.id] = {thang: thang, aether: @createAether(thang), castAether: null}
+    @thangs[thang.id] ?= {thang: thang, aether: @createAether(thang), castAether: null}
 
   canRead: (team) ->
     (team ? me.team) in @permissions.read or (team ? me.team) in @permissions.readwrite
diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee
index b34be2243..ddf76db03 100644
--- a/app/views/play/level/tome/tome_view.coffee
+++ b/app/views/play/level/tome/tome_view.coffee
@@ -47,6 +47,7 @@ module.exports = class TomeView extends View
     'tome:cast-spell': "onCastSpell"
     'tome:toggle-spell-list': 'onToggleSpellList'
     'surface:sprite-selected': 'onSpriteSelected'
+    'surface:new-thang-added': 'onNewThangAdded'
 
   events:
     'click #spell-view': 'onSpellViewClick'
@@ -65,14 +66,19 @@ module.exports = class TomeView extends View
       @cast()
       console.log "Warning: There are no Programmable Thangs in this level, which makes it unplayable."
 
+  onNewThangAdded: (e) ->
+    return unless e.thang.isProgrammable
+    @createSpells [e.thang]
+
   createSpells: (programmableThangs) ->
     # If needed, we could make this able to update when programmableThangs changes.
     # We haven't done that yet, so call it just once on init.
     pathPrefixComponents = ['play', 'level', @options.levelID, @options.session.id, 'code']
-    @spells = {}
-    @thangSpells = {}
+    @spells ?= {}
+    @thangSpells ?= {}
     for thang in programmableThangs
       world = thang.world
+      continue if @thangSpells[thang.id]?
       @thangSpells[thang.id] = []
       for methodName, method of thang.programmableMethods
         pathComponents = [thang.id, methodName]