Are we asking the right question?
It would certainly be interesting to know the earliest location where we can get a monster with a given ability, but we have access to more data than that, so we could actually answer a bigger question with the same effort. How about, "what are the locations where I can get a monster with the Auto-Bravery ability, sorted from earliest to latest?" We still need to find the earliest location where a tamable monster has the Auto-Bravery ability, but we can find out more this way. We've transformed the question from a linear search through the locations from earliest to latest into a filter-and-sort query, which is easy for a database to do.This filter-and-sort query is still more complex than previous questions because we're taking into account more types of data. Instead of just filtering monsters by ability, we also need to sort them by location, and to do that sorting, we need to know the order of the locations. We do have a complete ordering in the database table because the locations were added to the table in such a way that dependent locations were added after their source locations were added.
That's not the only valid ordering of the locations, though. Sometimes the game path forks, and in those cases the locations that both have the same source can be reached in either order. Since the locations make a tree graph with New Bodhum 003 AF at the root, we can add a depth attribute to the location table and assign each location a depth value based on how far it is away from the root. This depth value represents how many areas must be visited if we headed straight for the area in question. We could do this algorithmically, but the table only has 30 locations, so it's easy enough to assign by hand. We've added attributes to tables and views a half dozen times now, so I'll assume it's obvious how to do this and move on.
Sorting by Location Depth
Sorting by location depth isn't as hard as it may appear. We already have the filtering done between the links in the location table and the filter parameter processing in the monster controller, and we have the filtered list of monsters in the monster controller. All we have to do is sort that list by the location depth for where we can find each monster. Also, remember that a monster can be found in up to three different locations, so we're going to have to handle that detail as well. First, let's go ahead and add the sorting by location depth to the monster controller in app/controllers/monster_controller.rb:
class MonsterController < ApplicationController
def index
if params[:filter]
location = Location.find_by(name: params[:filter])
@monsters = location.location_monsters +
location.location2_monsters +
location.location3_monsters
elsif params[:ability_filter]
ability = Ability.find_by(name: params[:ability_filter])
@monsters = ability.get_all_monsters.sort_by { |monster| monster.first_location_depth }
elsif params[:skill_filter]
ability = RoleAbility.find_by(name: params[:skill_filter])
@monsters = ability.get_all_monsters.sort_by { |monster| monster.first_location_depth }
else
@monsters = Monster.all
end
end
def show
@monster = Monster.find(params[:id])
end
end
It ends up reading in code just about the same as it reads in the above description. I went ahead and did the sort on both abilities and skills here because it's the same code. Now, we need to define this first_location_depth method that we've called on the monster model. As long as it returns the depth of the location where the monster can first be found, sort_by will end up sorting the list of monsters the way we want it to. Here's one way to define that method in app/models/monster.rb:class Monster < ApplicationRecord
# ... A whole mess of belongs_to macros ...
def first_location_depth
[location&.depth, location2&.depth, location3&.depth].compact.min
end
end
We simply build up a short array of depths using the existence (&.) operator for each potential location, compact the array to remove the nil values for the locations that didn't exist, and return the minimum value. That's all there is to it. When we click on the Auto-Bravery ability in the ability table, we are presented with a list of monsters with that ability sorted by the depth of the first location where we can find them:What's Left?
Trying to automate this question of finding the strongest monsters also adds its own complications. What should we sort by, base strength, max level, or some combination of them? What if it's not what the user wants? Should we give the user the option? The solution to these questions will necessarily add complexity to the user interface that we should prefer to avoid. Side-stepping the issue and just not trying to do something for the user that is easier for them to do for themselves ends up being the better solution. We should always watch out for that simple case when designing a user interface.
Since we already have the feature of finding strong monsters in each location, the only things remaining are the two tables that we haven't connected: monster materials and monster characteristics. Monster materials is an interesting table that we can use to figure out how quickly we can level up the monsters we've tamed because we need to find the monsters that drop those materials that are used to level up our tamed monsters. However, enabling that feature is going to take a bit of work because the material table doesn't currently have the info for which monsters drop each material. We'll add that missing data and connect up that table next time.
Exploring Monster Taming Mechanics Table of Contents:
No comments:
Post a Comment