So I'm making a IRC betting bot. Basically the game/bot has three states of taking-in chat.

State 1 : Betting If anyone says "!bet team money" parse it and record.

State 2 : Battling Take nothing in, no more !bet etc. Just watch.

State 3 : Waiting/Bank Don't take bets. But take-in "!bank" and print out the users money count.

Right now for each of my bot message parsers I have a big fat IF.

if (global_state == BETTING): 
    blah blah bah

AND I'm starting to need to have my bot do stuff when the state changes. So now I'm starting to do this (which hurts my soul a little every time I read it)

if (global_state == BETTING && past_state == WAITING):
    do blah stuff like reset the bet money

As some of you might have noticed I'm using Python, but this problem definitely is not python-only. What should I do instead?

  • possible duplicate of Why is Global State so Evil? – gnat Jan 15 '15 at 6:54
  • @gnat Nope, I've done my thorough research. Plus Rob's answer is nothing like that question's answers. Hungry to close or flag a question? ;) – Louis Hong Jan 15 '15 at 7:06
  • @gnat I've developed a flag-phobia. Everytime, I'm paranoid that my question just isn't "unique" or "abstract" enough. If you check my Stackoverflow, you'll know what I sort of mean. – Louis Hong Jan 15 '15 at 7:13
  • you probably need to develop a thicker skin (in particular, learn that duplicate closures, unlike other kinds, are officially respectable). I myself have 20 or 30 questions closed as duplicates and am not ashamed of that. Nor do I hesitate to edit my question to highlight the difference, when I believe that duplicate is a misunderstanding - neither should you – gnat Jan 15 '15 at 7:19

This looks like a good application of the ideas of "Finite State Machine" and "Polymorphism".

You've already defined your states, so the next step is to define the transitions between states, and the behavior of the system when it's in each state.

There are many ways to implement state machines, but in this case you might benefit from three classes, one for each state. Each should have functions "parse(...)" and "transition(...)". The parse method just reads a line of input and does the right thing. The transition function decides what to do based on the new state that its going to, and returns the new state object.

(That's a very rough cut for the transition function; there are probably better ways to do it.)

Then your state variable, instead of referring to a string, actually refers to the current state object. Then you can use nice syntax like "global_state.parse(...)" and "global_state = global_state.transition(...)"

That's an extremely high-level view, and there are lots of ways to do it, but even if you just do that much, you'll get rid of almost all the big fat ifs in your program, and your heart will feel lighter.

  • Thanks, I like the humorous ending :) Perfect answer to my question. – Louis Hong Jan 15 '15 at 2:09
  • 2
    So I see that instead of somewhere in my code doing global_state = BETING I can do global_state.transition(BETTING) – Louis Hong Jan 15 '15 at 2:10
  • 1
    polymorphism will change your life :) – Rob Jan 15 '15 at 2:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.