fpclass / perpetual-haskelling-initiative

Main repository for the CS141 Perpetual Haskelling Initiative
MIT License
0 stars 0 forks source link

Basic game mechanics #4

Open mbg opened 4 years ago

mbg commented 4 years ago

We need to design the basic game mechanics and implement them, this probably includes:

lynchgeorge commented 4 years ago

If we are 'recreating' hearthstone (to some extent), we could have a set of different players/characters to pick from, which each have dedicated decks.

Maybe slightly dull, but the players could be programming languages. allowing for functional languages to be overpowered. Potentially functional languages could have a C'Thun-esque Monad card, and the Java deck could be 80% curly bracket minions

oscar-h64 commented 4 years ago

I think it would be a good idea to have FromJSON and ToJSON instances for the Deck type (and by extension we'd probably need it for the Card type), then users can save their decks as JSON files, and if we were using an API we'd likely use JSON to send decks also

mbg commented 4 years ago

Makes sense, although I suspect that a Deck type might just be something like type Deck = [Card] so it is really only the Card type that we would need to worry about since instance FromJSON a => FromJSON [a] already exists.

dixonary commented 4 years ago

@GLynch-code that's a very cool idea!

You could have a pool of "OOP" cards and "FP" cards that relevant languages could draw from, and maybe each language has a special passive ability?

Maybe Python's special ability is that it can include cards from both OOP and FP 😛

lynchgeorge commented 4 years ago

@dixonary That sounds a good idea, so like a base deck of the main paradigms, then 'expansion' decks of the specific languages. Due to timescale on this, for now we might just want to focus on base and a first expansion, but in the future you could release updated expansion relevant to any major changes that occurred with the language, for example the adaption of pattern matching.

lynchgeorge commented 4 years ago

My hearthstone is a little rusty, but for those expansion we could try and recreate the quests in hearthstone.

lynchgeorge commented 4 years ago

For example, for the java expansion we could recreate the Murloc Quest, playing 10 curly brackets fills your hand with syntax along with a try catch. Or it could be adapted for Haskell, 10 binds results in do notation etc, that sort of thing. To be honest most of the ideas are transferable. Ill look into the quests a bit more and post what I find back here.

dixonary commented 4 years ago

I think from the discussion on the Slack, we want the following basic rule set:

Keegan also provided some good example cards which can fit into particular paradigms.

lynchgeorge commented 4 years ago

To extend the cards/decks further

A deck would be a mix of base deck and expansion deck cards

So base decks could be OOP, Functional, Sequential (as examples) then expansion decks could be Java, Haskell, Python

lynchgeorge commented 4 years ago

Ideas for Specific Expansion sets (collected from the slack): C-thun-esque set, cards build up the 'strength' of a character over time Java expansion consists of curly bracket minions @keegan Scripts - These are cards with an Attack and HP value, that can be played onto the field Spells - Have no HP or Attack, affects existing cards according to the description Error - Cannot be played directly, cause negative effects while remaining in your hand Applicative - The specified effect is applied to all cards in hand/ on field Runtime Error - Cannot be played directly, reduces the number of available lambdas (mana) per turn by 1. IO - Has a 75% chance to 'upgrade' a card, increasing its stats, but a 25% chance to reduce it to a Runtime Error

= - Combines the effects of two cards into one. Removes any Errors. Foldr - Starting from the right, compresses all of your current cards on the field into a single card with all stats combined. Maybe - Attacks the right target 50% of the time. Otherwise, chooses between all available targets Monad Transformer - Convert all of the cards on your field into instances of Maybe. Binary Tree - Whenever this card is targeted, allow it to react first Hashmap - Summon a specified card from your deck Spaghetti Code - A low cost, low damage and low health card. Not the best, but does the job Waffles - Replace all cards on the field with Spaghetti Code Summoning Circle - Banish any non-Pure type card into Exile. Exiled cards are permanently removed from the game

oscar-h64 commented 4 years ago

What are the properties of each of the 3 card types, then we can implement the structures.

I believe all of them have a name, description, paradigm and program (their affects/what they do), then each card type will possibly have some extra things, but I don't know about the specifics

dixonary commented 4 years ago

Programs will need attack, health and cost Scripts will need cost Errors won't need anything, i guess?

lynchgeorge commented 4 years ago

Thinking of errors as types, i was thinking data Error = Program | Event/Scripts So for example, you cast a script, and then if it fails (because programming language is impure), then a Program or Script is played against you.

Also it might be worth implementing different types of scripts as a type, so like DamageScript, HealScript, that sort of thing. As some might regenerate health whereas some might do damage. Maybe its worth just sticking to those two types for the moment?

dixonary commented 4 years ago

I think that the idea is the card text should describe the effect that each script has - different scripts will have different effects, and they might be combined, eg. one script might hurt the enemy and heal you.

ghost commented 4 years ago

With the errors, is it that they can only be removed by another card that has 'remove an error' or something like that or will they have a specific kind of requirement to remove? If it is the latter then they may need to keep track of the requirement?

oscar-h64 commented 4 years ago

So as far as I can tell these is the properties needed for each type of card:

Program Script/Event Error
Name Name Name
Description Description Description
Paradigm Paradigm Paradigm
Program Program Program
Cost Cost
Attack
Health

We could have something like some scripts can remove all errors of a certain paradigm(s), that would just require a [Paradigm] field for scripts.

I'm not sure if we're calling them scripts or events

I'm assuming Cost/Attack/Health will be automatically generated from Program? Not sure though

If I've missed anything point it out and I'll edit this. If no one else wants it I'll open a PR and have a go

lynchgeorge commented 4 years ago

Im not sure on Program for Script/Event. Maybe we could define a type Action = Heal Int | Attack Int to determine what a Script does. Then we could just use [Action] for Scripts which have multiple effects And I think we should just call them Scripts, I think that's been mutually agreed over time, maybe?

lynchgeorge commented 4 years ago

And id be happy to start working on these, I feel this might be one of the things in the project I could actually program...... maybe that is yet to be seen lol

oscar-h64 commented 4 years ago

So Program is a list of instructions, I presumed that included attack and heal, maybe not though

And go for it, just to warn you when you change the definitions app/Main.hs will probably chuck out a load of errors

lynchgeorge commented 4 years ago

Oh i see, i missed that somehow. Maybe we should change the name of the Program (minion) and Program ([Instruction]) to avoid confusion.

oscar-h64 commented 4 years ago

We could rename [Instr] from Program to Action as its the action the card performs?

ghost commented 4 years ago

Action sounds fine to me. Also will we need a data type to represent the board (or the whole battle in general) when playing which can store information about each player's deck, board space, hand, dead programs (and anything else I am forgetting).

lynchgeorge commented 4 years ago

Maybe its worth having a Player data type, which stores what you said, and then having the board store the two current players?

ghost commented 4 years ago

Yeah that would make more sense. I would be willing to try program this, and some of the functions that would be needed to play, tomorrow, though I might need some help with things like randomising the deck as I haven't done random numbers in Haskell before.

oscar-h64 commented 4 years ago

This is useful, shuffleM or shuffle' should do exactly what you need, depending on whether you're in the IO monad or not at that point, you can work out with @GLynch-code exactly whose doing what

lynchgeorge commented 4 years ago

If im interpreting this correctly @oscar-h64 , the scripts could just be represented by Name, Description, Paradigm, [Action] and Cost Errors would have cost 0, then since Action = [Instr], ive defined Instr = Attack Int | Heal Int. so that should cover heal and attack on your original table.

However im not sure how we could extend this to also be a Program too, To distinguish between the Programs and Scripts there needs to be some sort of use count implemented.

For example, an action could have an extra int (ie a counter) associated to it if the card is a spell, that counter could = 1, and if its a Program it could be an int above the number of possible viable moves (e.g. counter = 200). Then when a card's actions are executed, the int could be decreased. If after an action was checked that int decreases to 0, the action should be removed from the [Action], then when [Action] is the empty list, the card would be removed from play?

But then the health would need to be encoded somehow.

lynchgeorge commented 4 years ago

Maybe its just easier to define data Card = Program | Script | Error, where Error = Program | Script

lynchgeorge commented 4 years ago

Whatever's decided ill get around to implementing in the morning

oscar-h64 commented 4 years ago

There was some discussion in #9, we decided 3 constructors would be better, so there would be 1 constructor for each card with the fields listed in the table (plus any I missed)

Specific comment: https://github.com/fpclass/perpetual-haskelling-initiative/pull/9#issuecomment-627339879

lynchgeorge commented 4 years ago

Yeahp, i see that now. A much simpler solution!

oscar-h64 commented 4 years ago

I think we've done the data structures (although Instr is still a work in progress), so now its time to move onto function implementations. There's now a Game.hs module which contains some important functions - processMove and setupGame.

setupGame takes the decks for player 1 and player 2 and generates the starting board and the starting player (1 or 2). This shouldn't be too bad as its mostly just filling in the defaults listed in the README then some random stuff like picking the starting player and shuffling the decks (this function isn't currently done in the IO or Handler monad, but it might be good to be so we can use the monadic random functions)

processMove takes a set of cards to play, the player who is playing those cards and the current board and attempts to complete the move. It has to sanity check the cards, making sure the player has enough points to play them etc (although checking they have the card and the move isn't empty is done by the server) and process the effects of the cards, so this is quite a big job - we can probably split it into smaller sections that different people can work on though.

I know @demonkittyRC was talking about doing some of this, anyone else want to help?

FergalOK commented 4 years ago

I'd be up for working with @demonkittyRC on this.

Though

oscar-h64 commented 4 years ago

Yeah there was a change to Board so that's redundant now (I believe this change is in #19)

I thought the player could play multiple cards so long as its within their cost limit for that turn, if not that's easy enough to change. We should also change the README if that's the case as that says cards not card.

ghost commented 4 years ago

Hey all,

Haven't had time to read all comments on this so far but I do have an understanding of hearthstone as well as a bit on battlegrounds and a few other card games, nothing too much but I play it a bit.

Anyways one interesting idea would be to implement PHP as a language (I know this may be considered heresy to some so hear me out), PHP would be the blue equivalent in mtg which is essentially debuffs, counterspells or any evasive effects hence it would be perfectly suited for such a broken language.

To the suggestion of combining programs on play this is close to the magnetic mechanic form hearthstone or the bestow for MTG where the difference being when bestow creature dies the minion becomes an independent living minion but in hearthstone it 'fully merges'. Both share effects or properties of minions.

There are potential for static counters which may be more prevalent maybe in java or perhaps for all languages/ classes which may match the c'thun or galakrond (this is one class instance) where independent cards in the set buff the single card (minions give +X/+X) wherever he is to c'thun and has size related battlecry, galakrond has an invoke ability that causes a different effect for each class and improves the card itself at intervals).

ghost commented 4 years ago

Also an interesting thing, do we have an idea for a Forbidden one Exodia win con?