[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Python
. . -> [Subject]  Python co-routines, how to use them?

Python co-routines, how to use them?

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1  2 3  

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #15 on Thu 13 Dec 2007 07:17 PM (UTC)

Amended on Thu 13 Dec 2007 07:18 PM (UTC) by Nick Gammon

Message
Quote:

Additionally, Lua doesn't have the built-in support for set objects ...


I am not trying to hijack this thread into "why don't you use Lua", however given that you want to use Python because it supports sets, and you also want to use coroutines, and this doesn't work (it says earlier this "freezes MUSHclient"), then I am trying to propose an alternative that will work.

As for sets, see:

http://www.lua.org/pil/13.1.html
http://lua-users.org/wiki/SetOperations

Lua tables do indeed, as David says, provide a simple way of testing for membership of an item, with no duplicates. Plus, the example from the Programming In Lua (pil) shows how you might do intersections and unions.

I seem to remember working on an affliction system earlier. I used a simple table to remember which afflictions you currently had (effectively a set of afflictions).

Then a second (ordered) table gave the desired cure order (and, for each affliction, what the cure was).

So, you go through the desired cure order in sequence, and for each one, you test for membership in the table of afflictions you actually have, and if you have that one, you cure it first.

This may not necessarily apply to your case, however the code looked neat enough.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #16 on Thu 13 Dec 2007 07:29 PM (UTC)
Message
Thank you for your efforts, Nick, and I certainly don't consider it as a 'just use Lua' statement. :) I use Lua for various simple scripts so I can basically muck my way around with it, but given the amount of code that is still okay (just the innards need a lot of mucking about) I am only considering a language switch as a very, very last choice.

Also, the system you are suggesting is a simplified version of what I already have in my current system. The new reworking of the innards is a radical change I am making exactly because the simpler approach isn't giving me all the flexibility and information I want to have.
[Go to top] top

Posted by Isthiriel   (113 posts)  [Biography] bio
Date Reply #17 on Thu 13 Dec 2007 08:00 PM (UTC)
Message
Python coroutines don't freeze MUSHclient; Python threads can cause MUSHclient to lose some of its responsiveness. MUSHclient only freezes if the main script thread blocks while waiting for the worker thread to free a lock.

(The responsiveness is lost due in equal parts to the GIL, the kind-of-sort-of-semi-random-round-robin scheduling algorithm and the varying granularity of context switches... I found out recently that Python's BDFL prefers fork().)

The art of Worstje's system is that it is tracking afflictions you potentially have and inferring what you do have without stopping to 'diagnose' the exact afflictions.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #18 on Fri 14 Dec 2007 03:09 AM (UTC)
Message
Sounds like it will be great when the kinks are ironed out. :)

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #19 on Fri 14 Dec 2007 05:33 AM (UTC)
Message
That's what I feel too, or I'd not be working on it still. :D

Only problem is that my mathematical skills are not good enough to switch from the semi-bruteforcing algorythm I use right now to a logical deducting that would have an O(n)-like execution time. I've been trying to bang my head at it for various months, showed it to some really brainy people and they couldn't figure out either whether there'd be a simpler and less cpu- and memory-intensive way to calculate it.
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #20 on Fri 14 Dec 2007 05:45 AM (UTC)
Message
Do you have a quick way of explaining what exactly you're trying to solve? Is there one of the posts here that explains it particularly well? I can take a crack at reorganizing the algorithm if you want...

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #21 on Fri 14 Dec 2007 04:04 PM (UTC)
Message
Not really; the easiest way for me would be to send you my prototype and show you the code (well over 1400 lines of code, where around 900 lines are the actual code being tested). I think I have some emails written in english that also discuss it, but it is all pretty specific.

First, a short notation explanation. Suppose you have the following affliction-set: (a, b, <c, d>, <c, e, f>). That would mean you have four afflictions: a, b, either c or d, and either c, e or f.

Now, when someone uses a skill at me which I can not exactly pinpoint the affliction of, I add a new affliction range (denoted by <>) with the proper afflictions. Against some classes, this is more a rule than an exception, where a problem props up: the data becomes superfluous and unmanagable to make sensible decisions off. Take the following example, where you'll be asking yourself: 'do I have a broken leg?'

I'll be simplifying the terms left leg, right arm etc to two letter equivalents (LA, RA, LL, RL) since it types a bit easier. Suppose you end up with the following knowledge: you have three broken limbs.

(<LA, RA, LL, RL>, <LA, RA, LL, RL>, <LA, RA, LL, RL>)

Three limbs. Simple logic says that this must equate to:

(<LA, RA>, <LL, RL>, <LA, RA, LL, RL>)

...thus, one arm, one leg, and one something else. However, we can take it even further:

(<LA, RA>, <LL, RL>, <LA, RL>)

In other words, we have narrowed it down greatly - reducing 12 total choices to only 6 possible choices. This makes the data more uniform and makes it easier to make decisions based on the knowledge we have. The more choices we have and the harder it is to tell how much of the information is useful, and how much is excessive and just grew while the system was in operation.

A big problem lies in making this uniform - no special handling for special afflictions. The various affliction-ranges theoretically offer you all the information you need (the logic doesn't need special information to know left leg and right leg are both legs, since they're both in the sets). The only method at which I have managed this so far is an optimized version of a brute force approach. It essentially goes like this:

1. Take the current afflictionset and calculate all possible results.
2. Now evaluate one of the affliction ranges in this afflictionset to a certain choice (eg <a, b, c> is made to be <a>), and calculate all possible results again.
3. If the resultsets are identical (represented by a frozenset of a frozenset of strings for easy comparison), we have deduced that this particular choice is spurious and unneeded.

Of course, the possible simplifications using this algorythm can change, so I try to evaluate into the most often occurring choices first since those have a bigger chance of matching. Results can still differ through various runs though (sets lack an order to iterate through them).

Additionally, the code also has to take chain-reactions into account (partially because the code has different classes for an afflictionrange and an absolutely 'set in stone' affliction, which need to be converted once only one choice remains). Also, due to illusions and false information, it can happen that you do not actually have an affliction because all possible choices disappeared at once.

Anyhow, the brute forcing mentioned above is what I am doing now. Anything simpler and less cpu- and memory-intensive is what I'm looking for.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #22 on Fri 14 Dec 2007 07:31 PM (UTC)
Message
OK, to try to understand this better can we introduce a bit more terminology?

Am I correct in thinking we have three main things here ...


  1. Some sort of attack, poison, disease that causes a problem to the target.

    For example:

    • A swing of the mace might break one or more limbs.
    • A poison might make you blind and silence you
    • A disease might reduce your stamina and cause damage over time


    Am I also correct in thinking you don't necessarily know what something does? So for example, if you previously had no broken limbs, and someone hits you with a mace, and now you have a broken limb, you conclude the mace caused it?

    In a more complicated case if a poison blinds and silences you, but you are already silenced, then you can't be sure if the receipt of the poison would have silenced you, or not, had you not been silenced already.

    I suspect this is unknowable, unless you happen to be perfectly healthy when you receive a certain sort of attack.

  2. The effects of attacks.

    These are the individual things that can be wrong with you. For example:


    • Broken left leg, broken right leg
    • Broken left arm, broken right arm
    • Silenced
    • Blind
    • Mad
    • Reduced stamina
    • Damage occuring over time


    There could be a many-to-many relationship here, I suppose, so that multiple poisons might send you mad, and an individual poison might cause two effects.

  3. The cures for effects.

    I presume you can take various cures, for example:


    • A banana reduces hunger
    • A spell cures a broken limb
    • A herb cures madness
    • A potion cures blindness


    I also presume you can have a many-to-many relationship again? Eg. a certain herb cures both madness and blindess.

    I also presume there is an optimal cure sequence, for example if you cannot eat, then that has to be cured before you can eat herbs to cure other things. Alternatively, you want to cure first the things that are causing the most damage.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #23 on Fri 14 Dec 2007 07:36 PM (UTC)
Message
The idea of illusions makes it harder. Is there a way of knowing, at some time, whether or not you have been tricked by an illusion?

If you definitely find out at some point, you might have to move an attack->effect set into a holding area, to be accepted or rejected as real or an illusion at a later time.

If it turned out to be an illusion, you discard it, if it turned out to be real, you merge it into your "known" area.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #24 on Fri 14 Dec 2007 07:58 PM (UTC)
Message
I already have a rudimentary - actually, it's pretty good - system in place to deal with illusions. However, if one sneaks through the code needs to be able to handle situations which end up as being impossible (an affliction running out of choices rather than resolving). That's about as far as the illusionhandling in the affliction-tracker goes.
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #25 on Fri 14 Dec 2007 09:07 PM (UTC)

Amended on Fri 14 Dec 2007 09:08 PM (UTC) by David Haley

Message
I see, thanks for the explanation. :) I have a question about these simplifications:

Quote:
(<LA, RA, LL, RL>, <LA, RA, LL, RL>, <LA, RA, LL, RL>)

Three limbs. Simple logic says that this must equate to:

(<LA, RA>, <LL, RL>, <LA, RA, LL, RL>)

...thus, one arm, one leg, and one something else. However, we can take it even further:

(<LA, RA>, <LL, RL>, <LA, RL>)


I don't believe it is as simple as you make it out to be, or maybe I'm missing an assumption you make. The expressions you wrote are not in fact logically equivalent: if you treat the first as:

(LA|RA|LL|RL) & (LA|RA|LL|RL) & (LA|RA|LL|RL)

and the second as:

(LA|RA) & (LL|RL) & (LA|RA|LL|RL)

and the third as:

(LA|RA) & (LL|RL) & (LA|RL)

you will note that the first expression is true when just LA is true but neither the second nor the third expression are true. In your simplifications, you seem to want to be saying that something from each of the three afflictions has to be true in the end of the day.

If that's what you mean to say, what it comes down to is that you not only have those three disjunctive guesses, but one of each must be true. In making the "simple logical simplifications" you described, you are in fact assuming this fact about each affliction being distinct.

Except what you wrote does not correspond to this assumption, because the simplified version is satisfied by just LA and LL being true, and all others being false.

So I'd like to hear more about the simplifications you made and how you justify them, i.e. what assumptions you are holding as you make those simplifications.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #26 on Fri 14 Dec 2007 09:29 PM (UTC)
Message
I am going to go out on a limb here *cough* and suggest that all you need is a count of broken arms/legs. Does it matter which leg it is?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Isthiriel   (113 posts)  [Biography] bio
Date Reply #27 on Sat 15 Dec 2007 04:42 AM (UTC)
Message
The thing with the afflictionsets is that you are guaranteed to have one affliction from each subset.

In the case of the broken limbs:
(<ll rl la ra>, <ll rl la ra>, <ll rl la ra>,)

We're saying that we currently have three skills affecting us, each of which could be afflicting any limb, so the possible actual afflictions (which we won't know until we diagnose) are:
1. (ll, rl, la) # no duplicates
2. (ll, rl, ra)
3. (ll, la, rl) # except these are sets, so this is identical to 1
4. (ll, la, ra)
5. (ll, ra, rl) # identical to 2
6. (ll, ra, la) # identical to 4
7. (rl, ll, la) # identical to 1
8. (rl, ll, ra) # identical to 2
9. (rl, la, ll) # identical to 1
10. (rl, la, ra)
11. (rl, ra, ll) # identical to 2
12. (rl, ra, la) # identical to 10

Now, we just spun out 12 possible choices from the original afflictionset and 8 of them were meaningless (and hence unnecessary work).

So the idea is to simplify the original afflictionset, preserving the 4 unique cases and reducing the number of duplicate possibilities.

If we look at: (<ll rl>, <la ra>, <ll, ra>) you'll notice the possibilities are:
1. (ll, la, ra)
2. (ll, ra ... can't choose from the last subset
3. (rl, la, ll)
4. (rl, la, ra)
5. (rl, ra, ll)
6. (rl, ra, ... can't choose again

We get the same 4 unique cases and do a bit less than half the work.

Now, knowing these are limbs and that three of four of them are broken we can enumerate the four unique cases by knowing that 4C3 is 4 and produce them by subtracting a limb from the set of four (that is the four unique cases are given by taking the set of four limbs and subtracting one limb in each) BUT Worstje is trying to make this as general as possible, so it doesn't know you have four limbs.


The problem is that expanding all possible choices is an O(NP) operation (factorial in fact, so worse than exponential order :( ). On the other hand, you have something like three billion cycles to play with.

Most skills apparently only give you a few possible afflictions, so you may need 20+ of them before the algorithm soaks up all of those cycles and is no longer useful. On the other hand there are some skills that can give you up to twenty possible afflictions and four skills like that make the algorithm useless (because it takes >10 seconds to come back with an answer, by which time the fight is nearly over).


... or at least that's the way I understand it.

Because this is trying to be an inference engine that can determine what afflictions you are certain to have from what afflictions you might have, and I think you need to specify which limb you are going to fix when curing, counting potentially broken limbs won't work :(

Though, having said that, I think being afflicted with (<ll, rl>, <ll, blind>, blind) might be a problem since (due to the arrival order) the possibilities are (rl, ll, blind) and (ll, blind). (I suppose a simpler example would be (<ra la>, ra) since you can't have your right arm doubly broken a second ra is a noop so your la isn't necessarily broken.)
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #28 on Sat 15 Dec 2007 05:35 AM (UTC)
Message
Crap, too many responses and too little time for me to reply. :D

Isthiriel pretty much hit the bullseye, except that it is a condition for my class that any choices that are already there for certain are removed, since they're not valid. E.g. (<LA, RA>, LA) is simplified into (<RA>, LA) and then (RA, LA).

Sadly I'm going to be out for the weekend, so the long and intensive replies to all I have just read may take a while.. thanks for all the input though, everyone. It is really appreciated.
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #29 on Sat 15 Dec 2007 11:14 PM (UTC)
Message
Quote:
The thing with the afflictionsets is that you are guaranteed to have one affliction from each subset.

I think you mean to say something stronger: what you described after that was actually that you are not only guaranteed to have one from each, but you must have a distinct affliction from each. In other words, it's not possible to pick the same affliction twice.

Now again, I don't know the relevant world that well, but it seems to me that assumption is too strong. I can picture several cases where two different attacks might give you the same affliction, like one could give you <LA, RA> and the other could give you <LA, LL>. And then, you could have gotten the left arm broken from both attacks. It would in this case be an error to "simplify" this to <LA,RA>, <LL>. But perhaps this is not true: perhaps it is in fact guaranteed that you will have a unique affliction given by each attack.

I believe you were pointing this out in this paragraph:
Quote:
Though, having said that, I think being afflicted with (<ll, rl>, <ll, blind>, blind) might be a problem since (due to the arrival order) the possibilities are (rl, ll, blind) and (ll, blind). (I suppose a simpler example would be (<ra la>, ra) since you can't have your right arm doubly broken a second ra is a noop so your la isn't necessarily broken.)

Cases such as these need to be handled in some sane way before you can start simplifying the more complex expressions. If <ra la>, <ra> can be reduced to merely <ra>, then as I said it is incorrect to conclude that <ra la ll rl>x3 will be reduced to the sets given: it could just as easily be <ra>x3 (where the last two would be "noops").

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


96,637 views.

This is page 2, subject is 3 pages long:  [Previous page]  1  2 3  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]