It is currently 29 Apr 2024, 12:41
   
Text Size

Computer is thinking

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Computer is thinking

Postby silly freak » 23 Sep 2009, 21:25

I got the "Computer is thinking" bug for the first time. In the console, there appears an Exception:
Code: Select all
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
   at java.util.ArrayList.RangeCheck(ArrayList.java:547)
   at java.util.ArrayList.get(ArrayList.java:322)
   at CardList.getCard(CardList.java:72)
   at CardList.get(CardList.java:73)
   at CardFactory$808.canPlayAI(CardFactory.java:25135)
   at ComputerAI_General.getMain2(ComputerAI_General.java:217)
   at ComputerAI_General.playCards(ComputerAI_General.java:48)
   at ComputerAI_General.main2(ComputerAI_General.java:43)
   at ComputerAI_Input.think(ComputerAI_Input.java:45)

   at ComputerAI_Input.showMessage(ComputerAI_Input.java:25)

   at GuiInput.setInput(GuiInput.java:27)
   at GuiInput.update(GuiInput.java:21)
   at java.util.Observable.notifyObservers(Observable.java:142)
   at java.util.Observable.notifyObservers(Observable.java:98)
   at MyObservable.updateObservers(MyObservable.java:12)
   at Phase.nextPhase(Phase.java:109)
   at GuiDisplay3$25.actionPerformed(GuiDisplay3.java:772)
   at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
   at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
   at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
   at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
   at javax.swing.plaf.basic.BasicButtonListener$Actions.actionPerformed(BasicButtonListener.java:287)
   at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1636)
   at javax.swing.JComponent.processKeyBinding(JComponent.java:2849)
   at javax.swing.JComponent.processKeyBindings(JComponent.java:2884)
   at javax.swing.JComponent.processKeyEvent(JComponent.java:2812)
   at java.awt.Component.processEvent(Component.java:5993)
   at java.awt.Container.processEvent(Container.java:2041)
   at java.awt.Component.dispatchEventImpl(Component.java:4583)
   at java.awt.Container.dispatchEventImpl(Container.java:2099)
   at java.awt.Component.dispatchEvent(Component.java:4413)
   at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
   at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:704)
   at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:969)
   at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:841)
   at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:668)
   at java.awt.Component.dispatchEventImpl(Component.java:4455)
   at java.awt.Container.dispatchEventImpl(Container.java:2099)
   at java.awt.Window.dispatchEventImpl(Window.java:2475)
   at java.awt.Component.dispatchEvent(Component.java:4413)
   at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
   at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
   at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
   at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
   at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
   at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
I think the cause is that swing catches the exception, which means the program continues. the highlighted line is where the buttons are disabled, but the buttons are not re-enabled as a result of the exceptional program flow.

the real problem is bugs in the card code. these cause the exceptions in the first place.
In my case, the computer wanted to activate a Lifespark Spellbomb (you can tell from the line in CardFactory):
Code: Select all
public boolean canPlayAI() {
    CardList land = new CardList(AllZone.Computer_Play.getCards());
    land = land.getType("Land");
    CardList basic = land.getType("Basic");
    if(basic.size() < 3) return false;
    Card[] basic_1 = basic.toArray();
    for(Card var:basic_1)
        if(var.isTapped()) basic.remove(var);
    basic.shuffle();
    if(basic.get(0) != null) {
        setTargetCard(basic.get(0));
        return true;
    }
    return false;
}//canPlayAI()
the if-condition throws an exception when all basic lands are tapped (--> list is empty)

fixed (& optimized; needs iterable card list) code:
Code: Select all
public boolean canPlayAI() {
    CardList land = new CardList(AllZone.Computer_Play.getCards());
    land = land.getType("Land").getType("Basic");
    for(Card var:land)
        if(var.isTapped()) land.remove(var);
    if(land.size() == 0 || land.get(0) == null) return false;
    basic.shuffle();
    setTargetCard(land.get(0));
    return true;
}//canPlayAI()
this is only an individual card fix; for the computer is thinking bug, a try/catch around calling card code should do the trick; i'll try to figure it out tomorrow
___

where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
silly freak
DEVELOPER
 
Posts: 598
Joined: 26 Mar 2009, 07:18
Location: Vienna, Austria
Has thanked: 93 times
Been thanked: 25 times

Re: Computer is thinking

Postby DennisBergkamp » 23 Sep 2009, 22:05

I've already fixed this bug in my local version, albeit a bit less elegant:

Code: Select all
public boolean canPlayAI()
        {
         CardList land = new CardList(AllZone.Computer_Play.getCards());
         land = land.getType("Land");
         CardList basic = land.getType("Basic");
         if (basic.size() < 3) return false;
         Card[] basic_1 = basic.toArray();
         for(Card var : basic_1)
            if (var.isTapped()) basic.remove(var);
          basic.shuffle();
          if (basic.size() == 0)
             return false;
          if (basic.get(0) != null) {
             setTargetCard(basic.get(0));
             return true;
          }
          return false;
        }//canPlayAI()
I've tested that, and it works. I mean, at least it doesn't cause the crash... however, it turns the land into a 3/3 until EOT, but then it still doesn't attack with it :roll:

I should really release the next version soon I guess, there are quite a few bug fixes I've done since. It would be a shame if other people do the same bug fix all over again.
But since it has a lot of the new cards, I think I'll hold off until Wizards releases their next version (Oct 2nd I think).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Computer is thinking

Postby silly freak » 24 Sep 2009, 09:39

yes, that's a good idea. as I said, this is an individual card fix. to ultimately stop the computer is thinking bug, I guess you have to add a try/catch in the AI code.
___

where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
silly freak
DEVELOPER
 
Posts: 598
Joined: 26 Mar 2009, 07:18
Location: Vienna, Austria
Has thanked: 93 times
Been thanked: 25 times

Re: Computer is thinking

Postby DennisBergkamp » 24 Sep 2009, 22:31

Yes, there's still quite a few "Computer is thinking..." bugs around. I don't think I've ever seen one that's related to an infinite loop, they're all either null pointer or array index out of bound exceptions.
I'll replace my code with your fix, since it's shorter and uses the iterable CardList :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Computer is thinking

Postby silly freak » 25 Sep 2009, 17:41

ok, i have a small patch for the problem, in ComputerAI_General:
Code: Select all
/**
 * Returns the spellAbilities from the card list that the computer is able to play
 */
private SpellAbility[] getPlayable(CardList l) {
    ArrayList<SpellAbility> spellAbility = new ArrayList<SpellAbility>();
    for(Card c:l)
        for(SpellAbility sa:c.getSpellAbility())
            //This try/catch should fix the "computer is thinking" bug
            try {
                if(sa.canPlayAI() && ComputerUtil.canPayCost(sa)) spellAbility.add(sa);
            } catch(Exception ex) {
                showError(ex, "There is an error in the card code for %s:%n", c.getName(), ex.getMessage());
            }
    return spellAbility.toArray(new SpellAbility[spellAbility.size()]);
}
This new Method implements the last path of the getMain1() and getMain2() method (that was clearly duplicated). The real change is the try-catch around the if that calls canPlayAI()
___

where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
silly freak
DEVELOPER
 
Posts: 598
Joined: 26 Mar 2009, 07:18
Location: Vienna, Austria
Has thanked: 93 times
Been thanked: 25 times

Re: Computer is thinking

Postby DennisBergkamp » 25 Sep 2009, 18:24

Cool, this should definitely help with finding those buggy cards , thanks :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 91 guests


Who is online

In total there are 91 users online :: 0 registered, 0 hidden and 91 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 91 guests

Login Form