Pidey's User customizable AI
Version: Alpha3
Introduction
This script not only provides an AI for one character, it also provides a way of modifying the AI while in game. This is done by inserting items that represent snippets of code into the "AI window"
Features
Screenshots
http://i12.photobucket.com/albums/a231/pidey/aidemopic.png
Script
Instructions
Place each of the above scripts in the game, I know that six is quite a few, but, they are all needed. Also download the attached file "highlighter" and put it in the pictures folder.
To bring up the AI editing screen, simply use the line $scene = Scene_grathe_code.new
Also, in scene_title, after command_new_game and in battle_test, insert these lines
in Scene_load add these lines after all of the marshal.load
In Scene_save, add these after all of the Marshal.dump
Also, I put various notes in the script in places that need to be customized for your specific game (my values are still in there)
Note1 This should be the number of the lowest action statement
Note2 This should be the number of the highest action statement
Note3 This should be the number of the lowest redirect statement
note4 This should be the number of the highest redirect statement
Note5 This should be the difference between the number of the lowest action statement and the number of the lowest redirect statement
Note6 Replace the 0 in this line with the location of the hero in the party (if he is 1st, keep it at 0, if he is 2nd, replace it with 1, if he is 3rd replace w/2, if he is 4th replace with 3.)
Note7 Here you have to impliment your own action lines, simply call action_passer(a,b,c)
A is 1 for a skill, and 0 for a regular action, B is the number of the skill, or for an action, 0 is attack, 1 is defend. Leave C to be -1, I can't fix it yet.
Note8 Replace the 83 with the skill you want performed upon failure of the AI.
Note9 Here is where the redirect lines are chosen, goto is a boolean, and simply make it true if you want it to redirect.
Note10 Here you can impliment the default AI. This section contains what item is in each line
Note11 Here you can impliment the default AI. This section contains where each line redirects to.
To add potential lines, dedicate a continuous chunk of 20 or so (more if you want) lines for actions, and THE SAME NUMBER for redirect statements. Name and description them appropriately, and then customize them where Note10 and Note11 are in the script.
-important-
Due to the myriad of Custom battle systems, the installation requires a little bit of scripting knowledge, have it so that when the character's turn comes up, execute $grathe_AI.main instead of executing his turn.
Also, this script uses variables 70-75, so don't use them in the game.
FAQ
Q.) do you plan on re-writing the script so it isn't such a PITA to impliment?
A.) I will consider it, just remember, it only needs to be implimented once.
Q.) Can I add my own lines?
A.) Yes, look above
Q.) Does it support more than one character?
A.) Not at this time, but you can have other characters that are not AI controlled.
Q.) OMG! CAN I HAVE YOUR BABIES?
A.) No, and if you take them anyway, you will be charged with kidnapping.
Compatibility
Currently unknown.... but it does use variables 70-75, so its not compatible with anything else that uses em.
Author's Notes
If you are having trouble figuring out how to modify a specific battle system to skip the guy's turn and instead use the AI, I can help with that.
Version: Alpha3
Introduction
This script not only provides an AI for one character, it also provides a way of modifying the AI while in game. This is done by inserting items that represent snippets of code into the "AI window"
Features
- Very customizable by the user
- Ability to customize limited by items, thus the game designer can gradually unlock this complex feature
- Easy to add new potential lines
Screenshots
http://i12.photobucket.com/albums/a231/pidey/aidemopic.png
Script
Code:
class GratheAI
def main
$game_variables[74]=1
if $game_variables[74] == 100
throw_error
end
while $game_variables[71] >= 105 && $game_variables[74] <= 100
execute_line
end
if $game_variables[71] == 0
$game_variables[75]+=1
$game_variables[74]=1
end
$game_variables[71]=500 #done so that the while statement isn't improperly tripped next time
end
def execute_line
$game_variables[71] = $grathe_code[$game_variables[75]] #Stores the contents of the current line
$game_variables[72] = $grathe_code2[$game_variables[75]] #Stores the location the line redirects to.
if $game_variables[71] >= 105 # this means its redirect statement
change_statement
else
chose_action
$game_variables[75]+=1
end
$game_variables[74]+=1
end
def chose_action
case $game_variables[71] #checks contents of current line
#Note7
when 83 #attack random
action_passer(0, 0, -1)
when 84 #Attack last
action_passer(0, 0, -1)
when 85 #defend
action_passer(0,1,-1)
when 86 #bullet rain
if $game_actors[6].sp>=50
$game_actors[6].sp -= 50
action_passer(1,100,-1)
else
throw_error
end
when 87 #recharge
$game_actors[6].sp += 35
action_passer(1,101,-1)
when 88 #Concentrate Fire
if $game_actors[6].sp>=50
$game_actors[6].sp -= 50
action_passer(1,102,-1)
else
throw_error
end
when 89 #double burst
if $game_actors[6].sp>=35
$game_actors[6].sp -= 35
action_passer(1,105,-1)
else
throw_error
end
when 90 #heal self
if $game_actors[6].sp>=5
$game_actors[6].sp -= 5
action_passer(1,106,-1)
else
throw_error
end
end
end
def throw_error
action_passer(1,83,-1) #Note8
end
def change_statement
goto = false
case $game_variables[71] #checks contents of current line
#Note 9
when 105 #a goto statement
goto = true
when 106 #SelfHP%>=25
# p (($game_actors[6].maxhp / 4) <= $game_actors[6].hp).to_s
goto = ($game_actors[6].maxhp / 4) <= $game_actors[6].hp
when 107 #selfMP>=50
goto = $game_actors[6].sp >= 50
when 108 #selfMP>=10
goto = $game_actors[6].sp >= 10
when 109 #random redirect
$game_variables[72] = rand(7).round
goto = true
when 110 #50% chance of redirect
goto = rand(2) == 1
when 111#10% chance of redirect
goto = rand(10)>=9
#Add additional Redirect statements here
end
if goto
$game_variables[75] = $game_variables[72]
else
$game_variables[75]+=1
end
end
#--------------------------------------------------------------------------
# * Force Action
#--------------------------------------------------------------------------
def action_passer(action_type, action_id, target)
# Ignore if not in battle
unless $game_temp.in_battle
return true
end
# Ignore if number of turns = 0
if $game_temp.battle_turn == 0
return true
end
# Process with iterator (For convenience, this process won't be repeated)
iterate_battler(1, 0) do |battler| #Note6
# If battler exists
if battler.exist?
# Set action
battler.current_action.kind = action_type
if battler.current_action.kind == action_id
battler.current_action.basic = action_id
else
battler.current_action.skill_id = action_id
end
# Set action target
if target == -2 # -2 means last enemy
battler.current_action.decide_last_target_for_actor
elsif target == -1 # -1 means random enemy
battler.current_action.decide_random_target_for_actor
elsif target >= 0
battler.current_action.target_index = target
end
# Set force flag
# If action is valid
if battler.current_action.valid?
battler.current_action.forcing = true
# Set battler being forced into action
$game_temp.forcing_battler = battler
# End
return false
end
end
end
# Continue
return true
end
#--------------------------------------------------------------------------
# * Battler Iterator (consider entire troop and entire party)
# parameter1 : If 0, enemy; if 1, actor
# parameter2 : If 0 or above, index; if -1, all
#--------------------------------------------------------------------------
def iterate_battler(parameter1, parameter2)
# If enemy
if parameter1 == 0
# Call enemy iterator
iterate_enemy(parameter2) do |enemy|
yield enemy
end
# If actor
else
# If entire party
if parameter2 == -1
# Loop for entire party
for actor in $game_party.actors
# Evaluate block
yield actor
end
# If single actor (N exposed)
else
# Get actor
actor = $game_party.actors[parameter2]
# Evaluate block
yield actor if actor != nil
end
end
end
end
Code:
# This class is used to allocate a storage for grathe's code.
# it stores what the contents of each line is, but not where each one redirects to.
class Grathe_Code_Bank
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@data = []
#Note 10
@data[1] = 111
@data[2] = 83
@data[3] = 105
@data[4] = 107
@data[5] = 87
@data[6] = 105
@data[7] = 86
@data[8] = 105
end
#--------------------------------------------------------------------------
# * Get Variable
# variable_id : variable ID
#--------------------------------------------------------------------------
def [](line_number)
if @data[line_number] != nil
return @data[line_number]
else
return 0
end
end
#--------------------------------------------------------------------------
# * Set Variable
# variable_id : variable ID
# value : the variable's value
#--------------------------------------------------------------------------
def []=(line_number, value)
if line_number <= 100
@data[line_number] = value
end
end
end
# This class is used to allocate a storage for grathe's code.
# This one stores where each if statement redirects to.
class Grathe_Code_Bank2
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@data = []
#Note11
@data[1] = 4
@data[3] = 1
@data[4] = 7
@data[6] = 4
@data[8] = 1
end
#--------------------------------------------------------------------------
# * Get Variable
# variable_id : variable ID
#--------------------------------------------------------------------------
def [](line_number)
if @data[line_number] != nil
return @data[line_number]
else
return 0
end
end
#--------------------------------------------------------------------------
# * Set Variable
# variable_id : variable ID
# value : the variable's value
#--------------------------------------------------------------------------
def []=(line_number, value)
if line_number <= 100
@data[line_number] = value
end
end
end
Code:
class Scene_grathe_code
def initialize
@current_line = 1
@selected_item=85
@item_type=0 #0 for an action, 1 for an if statement
$choosing_line = true
@status_window = Window_Grathe_status.new
@left_window = Window_Grathe_code_left.new(1)
@unused_window = Window_Grathe_unused.new(@selected_item, @item_type)
@help_window = Window_Help.new
end
def main
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
Graphics.freeze
@status_window.dispose
@left_window.dispose
@unused_window.dispose
@help_window.dispose
end
def update
@unused_window.refresh(@selected_item, @item_type)
@left_window.refresh(@current_line)
@status_window.refresh
if $grathe_code[@current_line] == 0
@help_window.set_text("")
else
@help_window.set_text($data_items[$grathe_code[@current_line]].description)
end
if $choosing_line
choose_line
else
choose_item
end
end
def choose_item
if @item_type == 0
c = 83 #Note1
d = 103 #Note2
else
c =105 #Note3
d =125 #Note4
end
if Input.trigger?(Input::UP)
if @selected_item > c
@selected_item-= 1
else
$game_system.se_play($data_system.cursor_se)
end
end
if Input.trigger?(Input::DOWN)
if @selected_item < d
@selected_item+= 1
else
$game_system.se_play($data_system.cursor_se)
end
end
if Input.trigger?(Input::LEFT)
if @item_type == 1
@selected_item-=22 #Note5
@item_type=0
$game_system.se_play($data_system.decision_se)
else
$game_system.se_play($data_system.buzzer_se)
end
end
if Input.trigger?(Input::RIGHT)
if@item_type == 0
@selected_item+=22 #Note5
@item_type = 1
$game_system.se_play($data_system.decision_se)
else
$game_system.se_play($data_system.buzzer_se)
end
end
if Input.trigger?(Input::B)
$choosing_line = true
end
if Input.trigger?(Input::C)
if $game_party.item_number(@selected_item) >=1 and $grathe_code[@current_line] != @selected_item
$game_party.lose_item(@selected_item, 1)
$grathe_code[@current_line] = @selected_item
$game_system.se_play($data_system.equip_se)
$choosing_line = true
else
$game_system.se_play($data_system.buzzer_se)
end
end
@status_window.refresh
@left_window.refresh(@current_line)
@unused_window.refresh(@selected_item, @item_type)
end
def choose_line
if Input.trigger?(Input::UP) # for when up is pressed
if @current_line > 1
@current_line -= 1
else
$game_system.se_play($data_system.cursor_se)
end
end
if Input.trigger?(Input::DOWN)
if @current_line < 150
@current_line += 1
else
$game_system.se_play($data_system.cursor_se)
end
end
if Input.trigger?(Input::RIGHT)
$grathe_code2[@current_line]+=1
end
if Input.trigger?(Input::LEFT)
$grathe_code2[@current_line]-=1
end
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Menu.new(6)
return
end
if Input.trigger?(Input::C)
$choosing_line = false
end
@status_window.refresh
@left_window.refresh(@current_line)
@unused_window.refresh(@selected_item, @item_type)
end
end
Code:
class Window_Grathe_code_left < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize(selectedline)
super(0, 64, 320, 416)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = $fontsize
refresh(selectedline)
end
def refresh(selectedline)
self.contents.clear
if $choosing_line
bitmap = RPG::Cache.picture('Highlighter')
self.contents.blt(-19,-82, bitmap, Rect.new(0, 0, 640, 640))
end
determine_line(selectedline-4,16)
determine_line(selectedline-3,48)
determine_line(selectedline-2,80)
determine_line(selectedline-1,112)
determine_line(selectedline,176)
determine_line(selectedline+1,240)
determine_line(selectedline+2,272)
determine_line(selectedline+3,304)
determine_line(selectedline+4,336)
end
def determine_line(linetodraw,y)
if linetodraw<=0 or linetodraw > 150
return true
else
self.contents.draw_text (16, y, 48, 32, linetodraw.to_s)
draw_item_name($data_items[$grathe_code[linetodraw]],58,y)
self.contents.draw_text(250,y,64,32, $grathe_code2[linetodraw].to_s)
end
end
end
Note: This window doesn't do anything currently, but its a goodplace to put.... something.
Code:
class Window_Grathe_status < Window_Base
def initialize
super(320, 64, 320, 180)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = $fontsize
refresh
end
def refresh
end
end
Code:
class Window_Grathe_unused < Window_Base
def initialize(x,y)
super(320, 244, 320, 236)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = $fontsize
@llega = 0
refresh(x,y)
end
def refresh(a,b)
self.contents.clear
if b == 0 #action
c = 83 #Note 1
d = 103 #Note 2
else #a redirect
c =105 #Note 3
d =125 #Note 4
end
if !$choosing_line
bitmap = RPG::Cache.picture('Highlighter')
self.contents.blt(-19,-164, bitmap, Rect.new(0, 0, 640, 640))
end
if b #drawing actions, items 83-103
draw_item_name($data_items[a], 64, 96)
self.contents.draw_text(16,96,64,32, $game_party.item_number(a).to_s)
if a-1>=c # Ensures it doesn't draw an item that isn't of the right type.
draw_item_name($data_items[a-1], 64, 48)
self.contents.draw_text(16,48,64,32, $game_party.item_number(a-1).to_s)
if a-2>=c
draw_item_name($data_items[a-2], 64, 16)
self.contents.draw_text(16,16,64,32, $game_party.item_number(a-2).to_s)
end
end
if a+1<=d
draw_item_name($data_items[a+1], 64, 144)
self.contents.draw_text(16,144,64,32, $game_party.item_number(a+1).to_s)
if a+2<=d
draw_item_name($data_items[a+2], 64, 176)
self.contents.draw_text(16,176,64,32, $game_party.item_number(a+2).to_s)
end
end
end
end
end
Instructions
Place each of the above scripts in the game, I know that six is quite a few, but, they are all needed. Also download the attached file "highlighter" and put it in the pictures folder.
To bring up the AI editing screen, simply use the line $scene = Scene_grathe_code.new
Also, in scene_title, after command_new_game and in battle_test, insert these lines
Code:
$grathe_code =Grathe_Code_Bank.new
$grathe_code2 =Grathe_Code_Bank2.new
$grathe_AI = GratheAI.new
in Scene_load add these lines after all of the marshal.load
Code:
$grathe_code = Marshal.load(file)
$grathe_code2 = Marshal.load(file)
$grathe_AI = Marshal.load(file)
In Scene_save, add these after all of the Marshal.dump
Code:
Marshal.dump($grathe_code, file)
Marshal.dump($grathe_code2, file)
Marshal.dump($grathe_AI, file)
Also, I put various notes in the script in places that need to be customized for your specific game (my values are still in there)
Note1 This should be the number of the lowest action statement
Note2 This should be the number of the highest action statement
Note3 This should be the number of the lowest redirect statement
note4 This should be the number of the highest redirect statement
Note5 This should be the difference between the number of the lowest action statement and the number of the lowest redirect statement
Note6 Replace the 0 in this line with the location of the hero in the party (if he is 1st, keep it at 0, if he is 2nd, replace it with 1, if he is 3rd replace w/2, if he is 4th replace with 3.)
Note7 Here you have to impliment your own action lines, simply call action_passer(a,b,c)
A is 1 for a skill, and 0 for a regular action, B is the number of the skill, or for an action, 0 is attack, 1 is defend. Leave C to be -1, I can't fix it yet.
Note8 Replace the 83 with the skill you want performed upon failure of the AI.
Note9 Here is where the redirect lines are chosen, goto is a boolean, and simply make it true if you want it to redirect.
Note10 Here you can impliment the default AI. This section contains what item is in each line
Note11 Here you can impliment the default AI. This section contains where each line redirects to.
To add potential lines, dedicate a continuous chunk of 20 or so (more if you want) lines for actions, and THE SAME NUMBER for redirect statements. Name and description them appropriately, and then customize them where Note10 and Note11 are in the script.
-important-
Due to the myriad of Custom battle systems, the installation requires a little bit of scripting knowledge, have it so that when the character's turn comes up, execute $grathe_AI.main instead of executing his turn.
Also, this script uses variables 70-75, so don't use them in the game.
FAQ
Q.) do you plan on re-writing the script so it isn't such a PITA to impliment?
A.) I will consider it, just remember, it only needs to be implimented once.
Q.) Can I add my own lines?
A.) Yes, look above
Q.) Does it support more than one character?
A.) Not at this time, but you can have other characters that are not AI controlled.
Q.) OMG! CAN I HAVE YOUR BABIES?
A.) No, and if you take them anyway, you will be charged with kidnapping.
Compatibility
Currently unknown.... but it does use variables 70-75, so its not compatible with anything else that uses em.
Author's Notes
If you are having trouble figuring out how to modify a specific battle system to skip the guy's turn and instead use the AI, I can help with that.