Aimy

The Core Mission

The core package currently provides, at least to some degree, each of these features:

Multiple Language Support

There's not much in the way of language assets now, but here's how to use them. I did up a 'pirate' language file so you'll see the difference. You can find text assets in the aimy/asset/text directory. The files should be named for the language code. Currently there's only 'en' and 'pirate'.

import core

# Create a core object.
o = core.Object()

# Print the current (default) language code
o.lang # 'en'

# Here's how to convert an error code to a
# text string.
print o.text('core-already-set')

# Now change the language code to 'pirate'
o.lang = 'pirate'

# Now you can view the message in piratese (if
# you happen to understand that language).
print o.text('core-already-set')

Thread-Optional Time Sharing

A meaningful AI needs the ability to do a lot of things at once without stumbling, so thread-optional processor time sharing is implemented at a very low level in the core package. The ORISC class implements open(), run(), io(), stop(), and close() methods to this end. Most of the higher-level core classes will be based on ORISC.

Agents provide communication between ORISC-based objects. Agents receive and handle commands. The next example uses Agent objects to demonstrate three ways to share processor time: Manually, Automatically, in threads, or automatically without threads.

One Step at a Time

First, take a look at the io() method, where ORISC-based objects perform their various functions. This is useful for testing time-sensitive operations or to discover what's happening step by step.

import core.agent

# Create an agent
james = core.agent.Agent()

# Send james his orders
c = james.command('output', "Bond...")

# The io() method is where the action takes place
james.io()

# Nothing happens until io() is called.
c = james.command('output', "James Bond.")

Continuously in a Thread

The Agent class inherrits serveral convenience methods, including a start() method to run the object processing in a thread.

import core.agent

# Create an agent
austin = core.agent.Agent()

# Send austin a command. Nothing will happen until
# io() is called.. .
c = austin.command('output', "This looks like a job for...")

# The start() method calls run() in a new thread,
# and then returns. The run() method repeatedly
# calls io() then sleeps a short while.
austin.start()

# If you send another command while threaded, it 
# will happen without explicitly calling io().
c = austin.command('output', "Double Oh Baby!")

Running Without Threads

The run() method calls io() repeatedly with no sleeping after each call to io(). Control is not returned until something causes the run loop to break.

Note that you'll have to interrupt (or close) the python interpreter (or kill your script process) to end the last section of this next sample.

import core.agent

# Create an agent
a = core.agent.Agent()

# Send a command, which will execute when io()
# is called.
a.command('output', "Once you run(), forget it!")

# Run. Use control-c to interrupt.
a.run()

Uninterrupted Runtime Reload

Agents provide communication between ORISC-based objects. Agents receive and handle commands. The following example demonstrates how to set core objects by setting an Agent in the core. The agent will be given a command to handle, and will then hold on to that command over the course of a coreload() - then execute it afterward.

Version 0.0011 introduced a new, more stable mechanism for handling runtime reloads. Use the core.Core class to contain any core object. Call the core.coreload() method to initiate a coreload.

import core

# For uninterupted service, create a Core object
# passing the configuration for the object that
# will contain all others. For this simple example,
# we only need a default Agent object, so it's OK
# to pass a string specifying the type.
app = core.Core('core.agent.Agent')

# You must open the app to create the root object,
# an Agent.
app.open()

# The root object is always stored in the Core
# object's root property. In the following line
# we give the Agent (root) a command to handle.
c = app.root.command('output', "I'm an Agent!")

# Call io() to execute the command, and see the
# result.
app.root.io()

# Now give root another command to see if it can
# reload without interruption.
c = app.root.command('output', "I can survive a coreload!!")

# Call coreload. This reloads all project packages.
app.coreload()

# The app object keeps track of 'agent' for you and
# continues operation as though the reload hadn't 
# happened.
app.root.io()

Human-Friendly Networking Classes

A meaningful AI needs the ability to find answers to questions and to interface with you, other people, and information sources on the internet.

Socket Connections

One of the most basic classes for connecting is the Connect class, implemented for internet communication by the Socket class. It's a fairly raw way to work - a tool for providing more human-friendly classes in the future.

import time, core.connect

# The Socket class can accept a URL given as text.
s = core.connect.Socket()

# Connect to the specified server (in this thread)
s.open('http://aimy.sourceforge.net/README.txt')

# Start processing input/output (in a thread)
s.start()

# Send a GET request
s.write('GET %s HTTP 1.1\r\n' % s.url.path)

# HTTP 1.1 requires at least a Host header
s.write ('Host: aimy.sourceforge.net\r\n\r\n')

# Give the server a chance to handle the request
time.sleep(0.5)

# Print the results. (Repeat the next line if there 
# seems to be more to read.)
print s.read()

Server Connections

The Server and Handler classes make it fairly easy to implement server connections.


# start an echo server listening on port 999
import core.service as ss
s = ss.Server(handler='core.service.handler.Echo')
s.start(999)

# create a connection to the server at 999
import time, core.connect as cc
c = cc.Socket('localhost:999')
c.start()

# take a moment to start the connection 
time.sleep(0.35)

# send echoserv some text...
c.write('What did I say?')

# Give the server time to reply, then read
# again.
time.sleep(0.35)
print c.read()