|
Wyvern uses lots of Lists, Sets, Hashes, Arrays, and other
data structures in its arguments. This tutorial will show
you how to read and manipulate them.
As an example, the wyvern.lib.GameMap
interface has a getMonsterList() function
that returns a Set of the monsters in the map. (Sadly, it's
a poorly-named function - should have been called getMonsters()).
Quickie Definitions
There are four main kinds of data structures used in Wyvern:
- List - a sequential, ordered list of items.
You can get the first item, the second item, and so on.
- Set - an unordered "bag" of items. They're not
numbered, and they can be returned in any order.
- Map - a set of unordered key/value pairs. By
far the most common example is every game object's
property list. The keys are property names, like
"level", and the values are miscellaneous objects
like Integers, Strings, Booleans, and Beans. Sometimes
a Map is also called a "Dictionary".
- Array - a sequential, ordered list of items,
just like a List. You don't see them as often as
you see Lists. There are some performance differences
between Arrays and Lists, but nothing that you really
need to care about right now.
Sometimes you'll see specific subclasses in the API, such
as LinkedList, ArrayList, HashSet, HashMap, and TreeMap.
Don't worry too much about those for now. The nice thing is
that they're all accessed the same way, which we'll explain
below.
Python has its own set of data structures (arrays, lists,
maps, and so on) with its own specific language constructs
for creating and manipulating them. You are more than welcome
to use them for your own purposes. However, you'll need to use
this code in this tutorial when you're manipulating Wyvern
built-in data structures (since they're written in Java).
Many of the Wyvern game classes return one of the four
standard data structures, or take one as a parameter.
For example, there's a method called
wyvern.lib.GameMap.getObjectsAt(x, y)
That returns a List of the objects at location (x, y).
The list is just like any other list, and you can do
all the normal operations to it that we cover below.
Accessing Values
There are four fundamental operations for every data
structure:
- get() - retrieves an item from
a data structure.
- add() (or
put() for Maps) - sticks an
item (or key/value pair) into the data structure.
- contains() - tells you if an
object is contained in the data structure.
- iteration - this is where
you process every item in the data structure. It's
got a special section below.
It's very convenient to have the List, Set and Map APIs
bookmarked, so you should bookmark to this link:
Java 2 Platform API
It has the Javadoc API documentation for all the Java classes.
The one you'll visit the most often is in the
Java 2 Platform Packages (in the right frame), under
the package java.util. It has the
API definitions for all the data structures that Wyvern uses.
For example, you can click on the List interface, scroll
down to the Method Summary, and see all the methods on List.
You have all of these methods available to you in your Wyvern
coding - in fact, you can call all of the thousands of methods
in the entire Java API.
In fact, you actually have access to three
complete API sets in Wyvern:
So your code in Wyvern is actually sitting on a truly gigantic
bundle of code, all of which you can use freely for your coding.
It helps to familiarize yourself with the tools you've got at
your disposal!
Iterators
You access all the data structures above (except Arrays)
using an Iterator. It goes through each item in the data
structure and returns them to you one at a time. Here's
the basic pattern:
<span class='keyword'></span>it<span class='keyword'></span> = <span class='keyword'></span>mylist<span class='keyword'></span>.<span class='keyword'></span>iterator<span class='keyword'></span>()<br><<span class='keyword'></span>font<span class='keyword'></span> <span class='keyword'></span>color<span class='keyword'></span>=<span class='string'>"<span class='keyword'></span>blue<span class='keyword'></span>"</span>><span class='keyword'></span>while<span class='keyword'></span></<span class='keyword'></span>font<span class='keyword'></span>> <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>hasNext<span class='keyword'></span>():<br> <span class='keyword'></span>item<span class='keyword'></span> = <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>next<span class='keyword'></span>()<br><span class='comment'> # ... do something with item ...</span>
|
This works identically for Lists and Sets, except that for
Sets, the items could come in any order.
For Maps, you can iterate over the keys or the values.
To iterate over the keys, do this:
<span class='keyword'></span>it<span class='keyword'></span> = <span class='keyword'></span>mylist<span class='keyword'></span>.<span class='keyword'></span>keySet<span class='keyword'></span>().<span class='keyword'></span>iterator<span class='keyword'></span>()<br><span class='keyword'></span>while<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>hasNext<span class='keyword'></span>():<br> <span class='keyword'></span>key<span class='keyword'></span> = <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>next<span class='keyword'></span>()<br><span class='comment'> # ... do something with key ...</span>
|
The best way to iterate over the values of a Map is to
iterate over the keys, and pull out the value for each key,
like so:
<span class='keyword'></span>it<span class='keyword'></span> = <span class='keyword'></span>mylist<span class='keyword'></span>.<span class='keyword'></span>keySet<span class='keyword'></span>().<span class='keyword'></span>iterator<span class='keyword'></span>()<br><span class='keyword'></span>while<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>hasNext<span class='keyword'></span>():<br> <span class='keyword'></span>key<span class='keyword'></span> = <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>next<span class='keyword'></span>()<br> <span class='keyword'></span>value<span class='keyword'></span> = <span class='keyword'></span>mylist<span class='keyword'></span>.<span class='keyword'></span>get<span class='keyword'></span>(<span class='keyword'></span>key<span class='keyword'></span>)<br><span class='comment'> # ... do something with value ...</span>
|
Deleting Items During Iteration
Sometimes you want to delete items from a data structure
as you're going through it. You can't just say list.remove(item),
because you'll get something called a
ConcurrentModificationException when
you try to do the next call to it.next().
Instead, the Iterator provides a remove()
method for you. To remove "rhialto" from a list of names, you'd
do this:
<span class='keyword'></span>it<span class='keyword'></span> = <span class='keyword'></span>namelist<span class='keyword'></span>.<span class='keyword'></span>iterator<span class='keyword'></span>()<br><span class='keyword'></span>while<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>hasNext<span class='keyword'></span>():<br> <span class='keyword'></span>name<span class='keyword'></span> = <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>next<span class='keyword'></span>()<br> <span class='keyword'></span>if<span class='keyword'></span> <span class='keyword'></span>name<span class='keyword'></span> == '<span class='keyword'></span>rhialto<span class='keyword'></span>':<br> <span class='keyword'></span>it<span class='keyword'></span>.<span class='keyword'></span>remove<span class='keyword'></span>()
|
Arrays
Note: for experienced Python programmers: when we say "Array"
here, we mean a Java array, such as
String[ ] names = { "Joe", "Fred", "Bob" };
You don't use Iterators to go through a Java array. Here's
the pattern:
<span class='keyword'></span>for<span class='keyword'></span> <span class='keyword'></span>i<span class='keyword'></span> <span class='keyword'></span>in<span class='keyword'></span> <span class='keyword'></span>range<span class='keyword'></span>(<span class='keyword'></span>len<span class='keyword'></span>(<span class='keyword'></span>myarray<span class='keyword'></span>)):<br> <span class='keyword'></span>item<span class='keyword'></span> = <span class='keyword'></span>args<span class='keyword'></span>[<span class='keyword'></span>i<span class='keyword'></span>]<br> ... <span class='keyword'></span>do<span class='keyword'></span> <span class='keyword'></span>something<span class='keyword'></span> <span class='keyword'></span>with<span class='keyword'></span> <span class='keyword'></span>item<span class='keyword'></span> ...
|
It's more or less like an Iterator. Here's a working example
that shows you how to use it. In this case, we've written an
object that provides a command called "argtest". When you
type "argtest" followed by some arguments, it prints out the
arguments you typed.
Note that we didn't actually parse the arguments - they come
pre-parsed in the CommandEvent passed into
Command.execute(). You can get them
via event.getArgs(), which returns an
Array of the arguments.
<span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>java<span class='keyword'></span>.<span class='keyword'></span>lang<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>String<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Command<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>kernel<span class='keyword'></span>.<span class='keyword'></span>maps<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>MapObject<span class='keyword'></span><br><br><span class='keyword'>class</span> <span class='function'>argtest</span>(MapObject, Command):<br><br> <span class='keyword'>def</span> <span class='function'>initialize</span>(self):<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>super__initialize<span class='keyword'></span>()<br><br><span class='comment'> # give it any old appearance</span><br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>setDefaultCategory<span class='keyword'></span>(<span class='string'>"<span class='keyword'></span>objects<span class='keyword'></span>"</span>)<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>setDefaultBitmap<span class='keyword'></span>(<span class='string'>"<span class='keyword'></span>jade_key<span class='keyword'></span>"</span>)<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>setProperty<span class='keyword'></span>('<span class='keyword'></span>short<span class='keyword'></span>', '<span class='keyword'></span>arg<span class='keyword'></span> <span class='keyword'></span>tester<span class='keyword'></span>')<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>setProperty<span class='keyword'></span>('<span class='keyword'></span>desc<span class='keyword'></span>', <span class='string'>"<span class='keyword'></span>type<span class='keyword'></span> <<span class='keyword'></span>font<span class='keyword'></span> <span class='keyword'></span>color<span class='keyword'></span>="</span><span class='keyword'></span>4169FF<span class='keyword'></span><span class='string'>">'<span class='keyword'></span>argtest<span class='keyword'></span> [<span class='keyword'></span>args<span class='keyword'></span>]' <span class='keyword'></span>to<span class='keyword'></span> <span class='keyword'></span>see<span class='keyword'></span> <span class='keyword'></span>your<span class='keyword'></span> <span class='keyword'></span>args<span class='keyword'></span>"</span></<span class='keyword'></span>font<span class='keyword'></span>>)<br><br> <span class='keyword'>def</span> <span class='function'>knowsCommand</span>(self, cmd):<br> <span class='keyword'></span>return<span class='keyword'></span> <span class='keyword'></span>String<span class='keyword'></span>.<span class='keyword'></span>startsWith<span class='keyword'></span>(<span class='keyword'></span>cmd<span class='keyword'></span>, <span class='string'>"<span class='keyword'></span>argtest<span class='keyword'></span> "</span>)<br><br> <span class='keyword'>def</span> <span class='function'>createEvent</span>(self, event):<br> <span class='keyword'></span>return<span class='keyword'></span> <span class='keyword'></span>event<span class='keyword'></span><br><br> <span class='keyword'>def</span> <span class='function'>execute</span>(self, event):<br><br> <span class='keyword'></span>agent<span class='keyword'></span> = <span class='keyword'></span>event<span class='keyword'></span>.<span class='keyword'></span>getAgent<span class='keyword'></span>()<br><br><span class='comment'> # this returns a string array</span><br> <span class='keyword'></span>args<span class='keyword'></span> = <span class='keyword'></span>event<span class='keyword'></span>.<span class='keyword'></span>getArgs<span class='keyword'></span>()<br><br> <span class='keyword'></span>for<span class='keyword'></span> <span class='keyword'></span>i<span class='keyword'></span> <span class='keyword'></span>in<span class='keyword'></span> <span class='keyword'></span>range<span class='keyword'></span>(<span class='keyword'></span>len<span class='keyword'></span>(<span class='keyword'></span>args<span class='keyword'></span>)):<br> <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>message<span class='keyword'></span>(<span class='keyword'></span>args<span class='keyword'></span>[<span class='keyword'></span>i<span class='keyword'></span>])</<span class='keyword'></span>pre<span class='keyword'></span>>
|
|