Modbot to Help You Run Games: Now With A Votecounter Demo!

This forum is for discussion related to the game.
User avatar
GreenLiquid
GreenLiquid
Mafia Scum
User avatar
User avatar
GreenLiquid
Mafia Scum
Mafia Scum
Posts: 1054
Joined: July 15, 2005

Post Post #75 (ISO) » Thu May 10, 2018 1:17 pm

Post by GreenLiquid »

I think I'm more or less done with my rewrite and I'd like to share what I've got in case you want to mine anything useful out of it or offer suggestions. I've cloned GitHub repositories for work but I've never added to one -- is that something I'm able to do with yours or do I need to create my own?
Avatar courtesy of Chickadee! | GTKAL
User avatar
Flubbernugget
Flubbernugget
Survivor
User avatar
User avatar
Flubbernugget
Survivor
Survivor
Posts: 11751
Joined: June 26, 2014

Post Post #76 (ISO) » Thu May 10, 2018 1:31 pm

Post by Flubbernugget »

I'm having a host of problems that seem to be related to how I configured git for a hackathon. I have to address this at a later time, and will integrate yessiree's work before a PR.

Sorry for the delay :/
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #77 (ISO) » Thu May 10, 2018 1:34 pm

Post by Psyche »

I think i pasted a contribution guide earlier green

And you can let me manage any merge issues; dont worry about integrating yessiree’s work; iirc there were some additions i was planning to make anyway
User avatar
yessiree
yessiree
he
Mafia Scum
User avatar
User avatar
yessiree
he
Mafia Scum
Mafia Scum
Posts: 4389
Joined: June 6, 2013
Pronoun: he

Post Post #78 (ISO) » Thu May 10, 2018 2:30 pm

Post by yessiree »

In post 69, Flubbernugget wrote:What's the difference between gevent and asyncio? I know what a coroutine is, but don't have much experience with either library.
both libs do the same thing, just in different ways. it really comes down to preference
User avatar
yessiree
yessiree
he
Mafia Scum
User avatar
User avatar
yessiree
he
Mafia Scum
Mafia Scum
Posts: 4389
Joined: June 6, 2013
Pronoun: he

Post Post #79 (ISO) » Thu May 10, 2018 2:33 pm

Post by yessiree »

To create pull requests, the simplest way would be to:

1. fork psyche's repo
2. clone the
forked
repo (not the main one)
3. push any commits you have to the forked repo
4. then go to the main repo, you should be able to create pull requests, more here: https://help.github.com/articles/creati ... om-a-fork/

Also yea, dont worry about integration. that's psyche's job :lol:
User avatar
GreenLiquid
GreenLiquid
Mafia Scum
User avatar
User avatar
GreenLiquid
Mafia Scum
Mafia Scum
Posts: 1054
Joined: July 15, 2005

Post Post #80 (ISO) » Thu May 10, 2018 4:59 pm

Post by GreenLiquid »

Alright, I got my files uploaded to a fork and I
think
I did the pull request right -- please let me know if I effed something up!

I had three main objectives for the code I've been working on:

1. Make it as robust as (reasonably) possible, so that mods with fairly bizarre or nonstandard voting rules in their setups can still make use of the tool, provided they're willing to put in the effort writing the config!
2. Make a standardized representation of the state of a game, and allow only clearly-defined operations upon it, called Events, which can be generated from JSON, so that other tools like Psyche's thread crawler can be utilized to create JSON events to be fed directly into the state object.
3. Make a system for turning the game state into posts like vote counts, player lists, role PMs, etc. in a way that is extremely customizable -- as Psyche said, mods have all sorts of ways they like to make their vote counts, so being able to accommodate all of them (including myself!) would probably be appreciated by a lot of users, and all the better if the method of customizing output does not require any Python or code knowledge whatsoever.

So, what exactly do I have so far? Basically, this:

Firstly, the classes and methods needed to create a "GameState" object which holds (ideally) the entire state of a particular game. Nothing is ever deleted out of the GameState: if a vote is no longer active (due to a player unvoting or voting for someone else), it gets its "end" timestamp set to reflect that. Consequently, it's possible to go to the GameState and ask for a vote count accurate to any post in the game, and it should be able to go back and pull a vote count for you. The code I have written in my Main.py currently does essentially that. The 'pie-in-the-sky' use for this would be, if for some reason this code were someday integrated into the site directly, that you could go to any post in a game, click a button, and a vote count as of that post would be generated for you. With a system like that, it might not even be necessary to have the mod post a vote count on every page. :P

Of course, this is all just me setting the bar high so as to encourage myself to make the system as robust as possible. Anyway, what all is included in this module?

The classes under the GameState umbrella would be:
GameState
: The container for all of the game's state data. Pretty straightforward.
Player
: The container for a particular player's data. This represents a 'slot' in the game, not a particular user who has been cast into that slot. A Player contains a list of all its users (needed to represent replacements), and also its role and alignment.
User
: A representation of a Mafiascum user. The "display_name" should be the user's MS username, and "aliases" can be used to store nicknames or hydra head names.
Phase
: A container for data corresponding to a phase of the game, e.g., Day, Night, etc. Each game starts in a phase called "Pregame" to represent the fact that the first day/night is not in effect the instant a game thread is made. The Phase abstraction exists so that, for instance, if a mod wanted to create a Nightless setup, or a variant setup with two lynching phases (Morning and Afternoon) for each night, they could do that without a lot of hassle.
PhaseType
: A representation of an idealized "type" of phase. For example, Day 2 is a particular phase that is an instance of the idealized "Day" phase. The "new" method is used to make a Phase from a PhaseType.
Election
: An election is any instance of an outcome being voted on in a game, most commonly a lynch vote (but it could be, for instance, the Social Policy vote from Civilization Mafia or w/e a mod wants). Each election corresponds to a phase and contains Electors and Votes.
ElectionType
: A representation of an idealized "type" of election. For example, the Day 3 lynch vote is an Election, and the type "Lynch" is an ElectionType.
Elector
: Any entity capable of voting or receiving votes in an election. Usually corresponds to a player, but I've created a separate object for it because 1) sometimes a label needs to be capable of receiving votes, e.g., a social policy in Civ Mafia or a bundle of players in a Partition game; and 2) a player might receive a modifier that only applies for a particular election and not in general, e.g., having doublevote for the lynch vote, but not for the vote for a town leader.
Vote
: A vote cast by an Elector for another Elector. Can have a "power" assigned to indicate the strength of the vote; for instance, a doublevoter casts votes with a power of 2.

There's also a couple of abstract classes that are inherited all over the place:
Temporal
: Anything that inherits Temporal has a start and end post, and helper methods like active() and past() to make it easier for other code to do time comparisons.
Modifiable
: Contains the Modifier class; any object that inherits Modifiable gets a dict called "modifiers" and some helper methods to add and fetch keys from it. The idea of this is to encapsulate special behavior into little tags that can be passed in via a configuration JSON string. Modifiers are Temporal and anytime a modifier changes, the old value of the modifier sticks around in the modifiers dict. The only use of this right now that I'm a little torn on is to track a player being alive -- a player with the "alive" == True modifier is considered alive, otherwise they're not. I did this just in case some weirdo mod wanted to make it possible to revive players in a game.

Then, to manage the GameState, you've got a couple of other classes:
Game
: This is just intended to be an interface into a GameState so it's not a massive pain to tell it to do things. The externally-accessible methods to Game should all be pretty self-explanatory, user-facing stuff. Still a major work in progress.
Event
: This is the part where I should make explicit that this code is
not
intended to go scrape pages for votes, as I think Psyche's already doing an amazing job on that front. Instead, I use JSON strings called Events to manipulate the GameState. Ideally, these should be the only interfaces into a GameState capable of modifying its state -- everything else should look and not touch. Events are things that happen that change the GameState, such as a "death" event for a player dying, a "vote" or "unvote" event for votes, a "vote_count" event to record that a vote count has been posted to the thread (handy if mods want their vote counts to link back to old vote counts), a "deadline" event when deadlines are set, a "phase_change" event when the phase changes (e.g., Day to Night), etc. etc. Events are loaded into the Game object (currently just from a file) using the load_events() method and then are processed using the process_events() method. The Game object keeps a big ol' list of events that it runs through in chronological order to calculate the GameState. Currently, I have no way to allow events to be processed out of order, so if an event is received out of order, the GameState has to be reset and calculated from scratch.

Right now, I've got a bunch of admittedly-pretty-bad code lying around that grabs the setup data and events data from JSON files in the repository (in the respective subfolders). These are just big chunks of JSON that contain the setup data and a huge list of all events, respectively. For my tests thus far, I've had to read through game threads myself and manually write event JSON for each thing that happens -- for an example of that, I recently wrote out the setup and event data for Mini Theme 1974 by hand, and put in some code needed to generate vote counts for it in the Main.py file. You can get a sense of how the JSON is laid out from that. I think it's going to be important to standardize the JSON for setups, events, votes, etc. earlier rather than later so please let me know if you have any suggestions for this! I've actually never worked with JSON before this project so there are undoubtedly some things I'm doing weirdly.

Finally, there are things I'm calling
Components
which are just ways to pull data from a GameState and its members and represent them in a lovely text format -- stuff like vote counts, player lists, role PMs (not there yet though), etc. I think this is easily the least intuitive part of what I've written here, but I like how modular it is so I'll take a stab at documenting it in the next couple of days so it's clear what it's doing. The important thing to note is that when you generate a vote count through the Game object, you can pass a Style in which tells the component how to format stuff. In Main.py I've passed in a style called "Micc" which just replicates the style of vote count Micc was using for Mini Theme 1974, just as a proof-of-concept for how customizing output works. All of the files for each style are in the "styles" subdirectory. Basically, you have two types of file inside each style:

- "body" files: These define the overall structure of each component. The "vote_count.component.body" file (i.e., the body file for the vote_count component) is probably the easiest to visually parse. The Component code just plugs 'n' chugs data into the body using Python's .format() function. And, yes, components can contain other components, so for instance, in order to represent the actual 'vote count' meat of a each vote count, I have a "list" subcomponent of newline-separated "vote_count_vote" components, which is a composite of the votee's "player_label" component, plus the a "list" subcomponent of comma-delimited "player_label" subcomponents for each voter. It's kind of messy but I think it'll be worth it, as mods can make a global change in their Style directory to how, say, they want player names displayed, and it'll affect all "player_label" components used anywhere in their Style.
- "configs" files: These are parameters to be passed into each component when it's created to define some customizable behaviors. For example, in the "_default" style, the "players_list" component gets a parameter passed in so that replacements for each player are displayed, as this is common practice for OPs pretty much everywhere. If for some reason a mod didn't want to display replacements, they could flip it to False in their own Style file.

... phew, anyway, I hope that was informative. I don't know how much interest there will be from others when it comes to using this, but I hope at least anyone who's interested will offer pointers and suggestions. Despite wanting to move professionally in that direction, I am not a developer, so undoubtedly the folks here who do this stuff for a living will be shaking their heads at some of what I'm doing here. Feedback (yes, negative feedback too) is very welcome!

So, first TODO for me: I really like the .md readme thing you have going on for ModBot, Psyche, so I'm going to try to create one for my files to make it easier for people to tell what the heck is going on.

Also, yea or nay on having most classes in their own file? I'm not sure if that's standard in Python world but it's what I've been doing up until now.
Avatar courtesy of Chickadee! | GTKAL
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #81 (ISO) » Thu May 10, 2018 5:17 pm

Post by Psyche »

woahh
this saves so much work!
ok i have a lot to digest before i can start fitting what you've made with what i've made, but it looks like you've done a great job to make all that pretty painless
i intend to read through every line of code and write a demo of it like what i did for the donbot module (whose name i now feel like ought to change to be more descriptive)
and more immediately interface it with the votecounter and votecountertester code i've been editting
i've been tracking votecounts with a separate VoteCount class, but hopefully I'll be able to use your gamestate stuff. We'll see!

anyway, i'll follow up again later as i digest more

EDIT: also your recent wall post is now the current readme for your gamestate folder. feel free to update it as you go.
Last edited by Psyche on Thu May 10, 2018 5:44 pm, edited 1 time in total.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #82 (ISO) » Thu May 10, 2018 5:43 pm

Post by Psyche »

Also, lately I've been grouping classes into files if they're likely to be used together or do sufficiently similar things. But I don't feel strongly one way or the other yet.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #83 (ISO) » Thu May 10, 2018 6:11 pm

Post by Psyche »

To Do:
-
Test and push yessiree's edits to sendPM() that enable sending a pm to multiple users rather than just one (and applies a bit of asynchronous processing to do it)

-
Update donbot.ipynb, donbotdemo.ipynb, and the donbot readme to reflect these changes

-
Push my pagetopper and prototypical interface code, as well as an extensive readme about packaging and exposing one's app over the web

-
Reorganize repository to be more descriptive and less labyrithine as our code base gets bigger

- Finish all those votecounter and votecounter tester edits, push them with a readme
- integrate votecounter with interface and pagetopper app so that we have a first version of a working automated pagetopping votecounter
- digest gamestate classes, integrate with votecounter
-
update the op...


This is getting a little unwieldy! I think I should probably divide between dev time and "repository cleaning/updating" time, doing the latter specifically when I'm distracted/not at 100%/unmotivated to write new stuff. Still, I'm bound to be lopsided one way or another. Okay, let's order this list according to priorities and workload.

I wanna go ahead and handle the sendPM() changes, and then focus on the interface and votecounter stuff so that we finally have a finished product. The other stuff will be on the backburner, only worked on when I don't have the will or need to work on the other stuff. These priorities will keep me plugging along without keeping me too focused solely on my corner of this project we're doing.

Let me know if any of you guys want any help figuring out what to do next!
Last edited by Psyche on Thu May 10, 2018 11:16 pm, edited 1 time in total.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #84 (ISO) » Thu May 10, 2018 7:40 pm

Post by Psyche »

have found that sequential sendPM() calls require a higher postdelay parameter than 1.5 (the default for donbot). For example, if you call

Code: Select all

bot = Donbot(username='Psyche', password='literallymypassword')
bot.sendPM('testing', 'test', 'Psyche')
bot.sendPM('testing', 'test', ['yessiree', 'vonflare'])
, only the first pm gets sent, but if you call

Code: Select all

bot = Donbot(username='Psyche', password='alsoliterallymypassword')
bot.sendPM('testing', 'test', 'Psyche')
bot.sendPM('testing', 'test', ['yessiree', 'vonflare'], postdelay=5)
, both pms get sent fine

I need to modify the donbot readme to be clearer about how important the postdelay parameter can be depending on what you're up to

anyway yessiree's changes are confirmed good!
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #85 (ISO) » Thu May 10, 2018 9:29 pm

Post by Psyche »

https://github.com/MafiaScum-Unofficial ... s/tag/v0.1

you can find my prototype of our client side tool for Windows 10 here; you should only need the exe file for this to work - no python or anything
opening the app should open your terminal, start a local server on your computer, and inform you in the terminal where to navigate your browser if you want to use the app
please let me know what you think of it

I created a repository of the associated code at https://github.com/MafiaScum-Unofficial ... ter/client
used the same structure as my donbot subdirectory, except here the README is identical in content to `YourPersonalModbot.ipynb`

i think i managed to make the underlying of the code app pretty simple and easy to understand, even if the packaged version takes up ~35mb...

first dependencies, then generic variables like the html structure of the app's different pages, then each of the flask app functions that dictate what happens when a request is made to one of the app's pages
growing this app should be as simple as adding the relevent generic variables, adding some new app functions, and updating older stuff like the index to include links to the new app function

Interested in making your instance of this application accessible over the web?
Consider Localtunnel: https://localtunnel.github.io/www/**
Once you install it with `npm install -g localtunnel`, entering `lt --port XXXX` where XXXX is the port of your currently active application server (eg 5000) should return a url you can use anywhere until you close it or lose connection. Be careful sharing your url.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #86 (ISO) » Fri May 11, 2018 12:26 am

Post by Psyche »

everything about my votecounter and votecounter tester just seems to be a lot slower when i organize things by classes
User avatar
yessiree
yessiree
he
Mafia Scum
User avatar
User avatar
yessiree
he
Mafia Scum
Mafia Scum
Posts: 4389
Joined: June 6, 2013
Pronoun: he

Post Post #87 (ISO) » Fri May 11, 2018 6:31 am

Post by yessiree »

might be time we started keeping track of the packages we installed with pip

https://pip.pypa.io/en/stable/reference ... pip-freeze

psyche you should add this to your list of todos for repo cleanup
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #88 (ISO) » Fri May 11, 2018 6:44 am

Post by Psyche »

kay
User avatar
yessiree
yessiree
he
Mafia Scum
User avatar
User avatar
yessiree
he
Mafia Scum
Mafia Scum
Posts: 4389
Joined: June 6, 2013
Pronoun: he

Post Post #89 (ISO) » Fri May 11, 2018 10:43 am

Post by yessiree »

@GreenLiquid, I skimmed over your code and think I got a good sense of what you're trying to do. The thing is a beast to say the least.

That said, I can't help but feel that we are approaching this with fundamentally different mindsets. I see that you are trying to record perfect history and store them in JSON files. Then you can generate whatever you need from these data. Whereas I'm only interested in data that are relevant to my needs, so most of the time it will be grabbing the most recent votes, generating a VC, and moving on.

Your approach is perfectly fine. I'm trying to think of what you'd need to automate the data generation process. You could write a crawler that monitors the thread and polls for every action that's worth collecting data for. Or you could write a program that starts scanning the thread only when you're asking something from it. You could keep track of the post number of where it left off last time it is ran though. Either way it's just something I wouldn't do, but if you could do this it would be pretty impressive, not to mention the data you collect would be invaluable.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #90 (ISO) » Fri May 11, 2018 11:03 am

Post by Psyche »

As soon who plans to use the infrastructure we're making to do research, I see a lot of benefits to a full game record approach. Also, when we scale our various tools up into a full "Modbot" that replace game moderators to the full extent possible (ie doing everything while a human being manages and is accountable for it), a "full game record" gains even more utility. Furthermore, users often appreciate having handily available detailed information about games (like full voting histories), and full game records could greatly advance the quality of our completed game archives.

At the same time, though, and this is what I'm finding as I develop my votecounter and votecounter tester, there's a bit of overhead associated with a comprehensive approach that could slow a client-side app down, even as layers of abstraction manage the additional complexity. For that reason, I think we should pick the most minimal representation that 1) solves whatever problem we're working on at the moment and 2) results in code that is easy to explain and understand - at least until we reach later stages in our project. Sometimes, that's something comprehensive, and other times that's not defining a class at all. We just gotta stay on our toes about this.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #91 (ISO) » Fri May 11, 2018 11:31 am

Post by Psyche »

speaking of which, for some reason making a proper votecounter tester that works as fast as what i made to support development of my own votecounter has turned out to be kinda difficult
i'm honestly sort of flabbergasted by its slowness; it seems to take 3 times as much time as my old thing, but the only change i've intentionally made was organizing the code into classes so that the tester could take a votecounter as an argument

i don't want to let that slow me down, so i'm gonna go ahead and take the votecounter I have now and add a demo app to the client-side app i released yesterday. For now but hopefully only for a while, my votecounter tester will remain a private tool to assist developing my own votecounter, rather than a public tool anyone can use to test their own stuff.

What votecounterdemo will do is take a threadurl, a playerlist, and a startpost and an endpost (expected to indicate the interval between the start of a phase and its ending), and extract an accurate votecount from that thread.

A full votecounter needs to do a bit more than that, as it needs to allow room for specifying vote-manipulating PRs, votecount formatting, and all kinds of game moderator preferences. It also needs to actually make posts, of course.

Anyway, think I'll have this demo done tonight or soon after.
User avatar
yessiree
yessiree
he
Mafia Scum
User avatar
User avatar
yessiree
he
Mafia Scum
Mafia Scum
Posts: 4389
Joined: June 6, 2013
Pronoun: he

Post Post #92 (ISO) » Fri May 11, 2018 2:01 pm

Post by yessiree »

why not just push what you have onto a separate branch and have other people look at it? git is literally the best tool for collaboration for situation like this

also, someone wise once said this: "premature optimization is the root of all evil". dont get too hung up on performance, focus on correctness and meeting your goals first. optimize only when necessary
User avatar
GreenLiquid
GreenLiquid
Mafia Scum
User avatar
User avatar
GreenLiquid
Mafia Scum
Mafia Scum
Posts: 1054
Joined: July 15, 2005

Post Post #93 (ISO) » Fri May 11, 2018 7:17 pm

Post by GreenLiquid »

In post 89, yessiree wrote:@GreenLiquid, I skimmed over your code and think I got a good sense of what you're trying to do. The thing is a beast to say the least.

That said, I can't help but feel that we are approaching this with fundamentally different mindsets. I see that you are trying to record perfect history and store them in JSON files. Then you can generate whatever you need from these data. Whereas I'm only interested in data that are relevant to my needs, so most of the time it will be grabbing the most recent votes, generating a VC, and moving on.

Your approach is perfectly fine. I'm trying to think of what you'd need to automate the data generation process. You could write a crawler that monitors the thread and polls for every action that's worth collecting data for. Or you could write a program that starts scanning the thread only when you're asking something from it. You could keep track of the post number of where it left off last time it is ran though. Either way it's just something I wouldn't do, but if you could do this it would be pretty impressive, not to mention the data you collect would be invaluable.
I think in hindsight I went a little bit crazy, but my aim has been to make the module robust enough for full automation to be possible in the distant future, and also to allow for games with very unorthodox or voting rules or powers. Hopefully with some decent UI design it will be possible to hide most of the complexity from end users unless they want to go ham automating a weird setup -- I'd like to make it completely painless to automate a "normal" game (even if only the day phases at this point).

If I integrate with Psyche's module it should be doable to create a crawler to monitor the thread, parse posts / PMs for events, and send out prods automatically. The part that's proving challenging right now is coming up with a model for this process that's absolutely as hardened as possible against race conditions and ill effects from, say, accidentally parsing one event before another. I have a few ideas on this front but I've been feeling sick today so that might have to happen next week.

I'd also like to make role abilities modular in the way Psyche was suggesting earlier in this thread. That'd make it easier for mods to create 'composite' roles like Mafia 2-Shot Macho Roleblocker / Even-Night Neighborizer, since they'd just have to supply the labels with the assurance that the logic for the 'normal' version of these roles is already built into the module. This piece on its own is probably going to be a huge amount of work.

Has anyone ever formulated the logic behind NAR in a way that can be easily adapted to an application? I can already see that challenge looming over the horizon. :P
Avatar courtesy of Chickadee! | GTKAL
User avatar
GreenLiquid
GreenLiquid
Mafia Scum
User avatar
User avatar
GreenLiquid
Mafia Scum
Mafia Scum
Posts: 1054
Joined: July 15, 2005

Post Post #94 (ISO) » Fri May 11, 2018 7:41 pm

Post by GreenLiquid »

My road map currently looks something like this:

Phase I - Manual Vote Gathering (Modbot as Assistant):
- Create a UI to make it easier to transcribe events than writing JSON by hand. I might be able to make this a new page in the Web app Psyche just created. That said, I'm utter garbage at UI and Web coding so that's going to be a learning experience. :lol:
- Also create a UI to make it easier to create the setup JSON file.
- Add additional functionality to Components -- basically, go rummaging through the game archives for every kind of OP and vote count variant I can dig up and make sure my Component logic can handle it (or have a good reason why not).
- Review and reorganize the Election logic -- it's currently a bit of a mess and the logic for multiple votes per player hasn't even been tested yet. I'd like to make that more modular so I can test the pieces in isolation.
- Create documentation and add comments.
- In general, make sure my code can play nice with other people's modules, in case they'd like to make use of it!

Phase II - Automatic Vote Gathering (Modbot as Auto-VC-Generator)
- Hook into the DonBot class with an interface that can turn votes it counts into Events to be passed to the GameState object.
- Finalize strategy for integrating parsing of posts with the event processing code -- i.e., how to minimize race conditions.
- Add logic to automatically detect when a lynch is achieved and reject vote changes in twilight.
- Hook the Generator class into the posting functionality of DonBot (and integrate with the pagetopper too) so that vote counts can be posted as they are generated.
- Test and harden the system -- Mafia games are very easy to ruin with even a minor slip-up, so the moduleneeds to be ironclad and there need to be fail-safes carefully considered and built in, especially surrounding player roles and alignments.

Phase III - Full Automation of Normal Games (Modbot as Fully-Functional Mod)
- Implement a module for tracking night actions and calculating results using NAR (this is going to be a biggie).
- Expand parsing logic to PMs and PTs, especially the scum PT.
- A whole bunch of other challenges I haven't even thought of yet.

Phase ?? - Full Automation of a Varsoon Game (Modbot as Obscene Pipe Dream)
- Grovel before AI overlords.
Avatar courtesy of Chickadee! | GTKAL
User avatar
GreenLiquid
GreenLiquid
Mafia Scum
User avatar
User avatar
GreenLiquid
Mafia Scum
Mafia Scum
Posts: 1054
Joined: July 15, 2005

Post Post #95 (ISO) » Fri May 11, 2018 7:47 pm

Post by GreenLiquid »

In post 91, Psyche wrote:speaking of which, for some reason making a proper votecounter tester that works as fast as what i made to support development of my own votecounter has turned out to be kinda difficult
i'm honestly sort of flabbergasted by its slowness; it seems to take 3 times as much time as my old thing, but the only change i've intentionally made was organizing the code into classes so that the tester could take a votecounter as an argument

i don't want to let that slow me down, so i'm gonna go ahead and take the votecounter I have now and add a demo app to the client-side app i released yesterday. For now but hopefully only for a while, my votecounter tester will remain a private tool to assist developing my own votecounter, rather than a public tool anyone can use to test their own stuff.

What votecounterdemo will do is take a threadurl, a playerlist, and a startpost and an endpost (expected to indicate the interval between the start of a phase and its ending), and extract an accurate votecount from that thread.

A full votecounter needs to do a bit more than that, as it needs to allow room for specifying vote-manipulating PRs, votecount formatting, and all kinds of game moderator preferences. It also needs to actually make posts, of course.

Anyway, think I'll have this demo done tonight or soon after.
I'm really looking forward to seeing the code for parsing posts for votes, as the level of D1 lynch accuracy you achieved with that thing is extremely impressive. In theory, if someone were using a ModBot to run their vote counts entirely, they could simply require players to format votes in an unambiguous way, but I like the added utility of the code being clever enough to figure out votes that don't adhere to a strict format. As you mentioned earlier, we could also use it to automatically collect full voting data from old games really quickly, which I'm sure our resident statisticians and number-crunchers in MD would adore. :)
Avatar courtesy of Chickadee! | GTKAL
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #96 (ISO) » Sat May 12, 2018 7:14 am

Post by Psyche »

kay im on the edge of uploading the cleaned up votecounter (an ipynb and an associated py file like normal), as well as votecounterdev.ipynb (the notebook i used to develop my votecounter, which includes my testing code) and my cleaned up subset of the content here as archive.txt: viewtopic.php?f=53&t=29549

While the linked archive has formatting inconsistencies, spelling mistakes, and other transcribing issues, archive.txt is less comprehensive (including ~300 games) but has much fewer of those issues, if any at all. It'll be useful when I return to doing research instead of building tools, and I imagine it'll be useful to a lot of other people too. However, my votecounterdev.ipynb is also based on a full scrape of the threads associated with these games, and while I may upload the notebook I scraped this information with, I won't be able to upload the scraped data itself, as it's too huge.

Anyway, immediate step after that is to prepare the vote counter demo for the client.
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #97 (ISO) » Sat May 12, 2018 11:59 am

Post by Psyche »

i seem to have introduced some bugs in translation, so hold off on tinkering w/ my code or whatever
my guess is that there are some big differences between the way i scraped the posts for my testing code and the way donbot.getPosts() scrapes posts, and that's making issues

also donbot.getPosts is buggy; i need to write better test code
User avatar
Flubbernugget
Flubbernugget
Survivor
User avatar
User avatar
Flubbernugget
Survivor
Survivor
Posts: 11751
Joined: June 26, 2014

Post Post #98 (ISO) » Sat May 12, 2018 4:51 pm

Post by Flubbernugget »

I had to set my PYTHONPATH to the directory with donbot.py to get imports to work.

Is this intended behavior?
User avatar
Psyche
Psyche
he/they
Survivor
User avatar
User avatar
Psyche
he/they
Survivor
Survivor
Posts: 10662
Joined: April 28, 2011
Pronoun: he/they

Post Post #99 (ISO) » Sat May 12, 2018 5:49 pm

Post by Psyche »

what i usually do is keep donbot.py in the same working directory as my script importing it
by the way, the current donbot.py is buggy and about to be updated!
Post Reply

Return to “Mafia Discussion”