For an Elm (0.13) game I'm developing, I'd like to have reconfigurable inputs. A simplified version of the model that I've got for this is
type Controls = {
up: KeyCode,
down: KeyCode,
left: KeyCode,
right: KeyCode
}
type Player = {
...
controls: Controls,
...
}
type Game = {
state: State,
players: [Player]
}
For the game loop, I'm using a standard foldp construction, where I'd like the input to be dependent of the current state of the game. So far I tried the following:
gameState =
let
initialGame = (newGame initialActive)
in
foldp update initialGame (input initialGame)
but of course, the input signal generating function (input : Game -> Signal Input) keeps on using the initial game, and not the changed gamestate.
I've searched troughout the internet to find a solution to this, but I couldn't find anything in this direction. Is there a way to do it the way I was trying (by including the controls in the model), or will I have to release the controls from the model by making the controls signals themselves?
There is a closely related question here: Creating custom keyboard controls [Elm]
If you want to, you can keep the Controls part of your game state. The way to do this is not to base your input on the initialGame, but to take more general input from which you can always extract what you need. In this case that would be Keyboard.keysDown. Then you can get the input for each player using:
playerInput : Controls -> [KeyCode] -> { x : Int, y : Int }
playerInput {up,down,left,right} kd =
List.filter (\ky -> List.member ky [up,down,left,right]) kd |>
List.foldl (\ky st -> if | ky == up -> { st | y <- st.y + 1 }
| ky == down -> { st | y <- st.y - 1 }
| ky == left -> { st | x <- st.x - 1 }
| ky == right -> { st | x <- st.x + 1 }
) {x=0,y=0}
If you want to remove Controls from Game you can hoist it up into the definition of the input for the foldp.
Related
I want to move an object in Haskell Gloss every frame a key is pressed, not just the one frame that the key is started being pressed. (Example: While 'w' key is pressed, accelerate object every frame)
Edit: I tried using the second parameter of EventKey but to no avail.
My code:
--TODO - Holding keys doesn't work yet
handleKeys :: Event -> AsteroidsGame -> AsteroidsGame
handleKeys (EventKey (Char char) _ _ _) game
| char == 'w' = move 0 1
| char == 'a' = move (-1) 0
| char == 's' = move 0 (-1)
| char == 'd' = move 1 0
where move x y = game {player = accelerateObject (player game) x y}
handleKeys _ game = game
accelerateObject :: Object -> Float -> Float -> Object
accelerateObject obj hor ver = obj {vel = (vx + hor, vy + ver)}
where (vx, vy) = vel obj
As OP correctly deduced, gloss gives you input events ("key was just pressed", "mouse was just moved"), rather than input state ("key is currently pressed", "mouse is at x,y"). There doesn't seem to be a built-in way to see input state on each frame, so we'll have to make our own workaround. Thankfully, this isn't too difficult!
For a simple working example, we'll make an incredibly fun "game" where you can watch a counter count upwards while the space bar is pressed. Riveting. This approach generalises to handling any key presses, so it'll be easy to extend to your case.
The first thing we need is our game state:
import qualified Data.Set as S
data World = World
{ keys :: S.Set Key
, counter :: Int }
We keep track of our specific game state (in this case just a counter), as well as state for our workaround (a set of pressed keys).
Handling input events just involves either adding a key to our set of currently pressed keys or removing it:
handleInput :: Event -> World -> World
handleInput (EventKey k Down _ _) world = world { keys = S.insert k (keys world)}
handleInput (EventKey k Up _ _) world = world { keys = S.delete k (keys world)}
handleInput _ world = world -- Ignore non-keypresses for simplicity
This can easily be extended to handle eg. mouse movement, by changing our World type to keep track of the last known coordinates of the cursor, and setting it in this function whenever we see an EventMotion event.
Our frame-to-frame world update function then uses the input state to update the specific game state:
update :: Float -> World -> World
update _ world
| S.member (SpecialKey KeySpace) (keys world) = world { counter = 1 + counter world }
| otherwise = world { counter = 0 }
If the spacebar is currently pressed (S.member (SpecialKey KeySpace) (keys world)), increment the counter - otherwise, reset it to 0. We don't care about how much time as elapsed between frames so we ignore the float argument.
Finally we can render our game and play it:
render :: World -> Picture
render = color white . text . show . counter
main :: IO ()
main = play display black 30 initWorld render handleInput update
where
display = InWindow "test" (800, 600) (0, 0)
initWorld = World S.empty 0
How do I write a predicate to check for a Horizontal, vertical or diagonal wins for a tictactoe game in Alloy? I'm kind of struggling with the syntax below is my code:
open util/ordering [Time] as T
sig Time {}
abstract sig Game {
turn, winner, loser: Game
}
abstract sig Player {
opponent:Player
}
sig X extends Player {}
sig O extends Player {}
fact {
all t:Time| all p: Player | no p.opponent
all t: Time | all p: Player | all g:Game | one g.turn
all t:Time | all g:Game | one g.winner & g.loser
}
pred HorizontalWin {
}
I think your model might not be appropriate for this game. For example, I don't see a 3x3 grid in your model, so it is not clear how to express any property about the state of the game.
There are several other issues with your model. For example, the Game sig is abstract and it has no concrete subsigs, so instances of this model can never contain any games (thus turn, winner, and loser fields will always be empty as well). Also, you probably want to use the Time signature somewhere (either put some fields in it, or make other fields use it, e.g., turn: Player -> Time) and then add some facts about every two consecutive time steps to properly connect the game moves. Here is an idea:
open util/ordering [Move] as M
abstract sig Player {}
one sig X, O extends Player {}
abstract sig Cell {}
one sig C00, C01, C02, C10, C11, C12, C20, C21, C22 extends Cell {}
sig Board {
grid: Cell -> lone Player
}
sig Move {
player: Player,
pos: Cell,
board, board': Board // pre and post board
} {
// must choose an empty grid cell
no board.grid[pos]
// set the `pos` cell to `player`
board'.grid[pos] = player
// all other grid cells remain the same
all c: Cell - pos | board'.grid[c] = board.grid[c]
}
fact {
// empty board at the beginning
no M/first.board.grid
all m: Move {
some M/next[m] => {
// alternate players each move
M/next[m].player != m.player
// connect boards
M/next[m].board = m.board'
}
}
}
run {} for 9 but 10 Board
I am visualizing a collection of process with GraphViz. Each process consists of some Read or Write operations in program order. Naturally, it is desirable to arrange the operations in the left-to-right order with respect to each process.
Using GraphViz (version 2.28), my code goes like this:
digraph G
{
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
0 -> 1 -> 2 -> 3 -> 4;
}
node [shape = box];
{rank = same;0;wy1;rf1;rc1;rz1;ry1;ra1;rb1;rx2;}
{rank = same;1;wf1;}
{rank = same;2;wx2;wc1;}
{rank = same;3;wf2;wz2;wx3;wa1;}
{rank = same;4;wz1;wy2;wx5;wb1;}
wy1 -> rf1;
rf1 -> rc1;
rc1 -> rz1;
rz1 -> ry1;
ry1 -> ra1;
ra1 -> rb1;
rb1 -> rx2;
wx2 -> wc1;
wf2 -> wz2;
wz2 -> wx3;
wx3 -> wa1;
wz1 -> wy2;
wy2 -> wx5;
wx5 -> wb1;
wf1 -> rf1[color = blue];
wc1 -> rc1[color = blue];
wz1 -> rz1[color = blue];
wy1 -> ry1[color = blue];
wa1 -> ra1[color = blue];
wb1 -> rb1[color = blue];
wx2 -> rx2[color = blue];
// W'WR Order:
wx3 -> wx2[style = dashed, color = red];
// W'WR Order:
wx5 -> wx2[style = dashed, color = red];
}
I am sorry to say that I am not allowed to post the output picture with too low reputation. If you can run the code, you will see that the result is not so satisfying due to the out of order in process with pid = 3. Specifically, GraphViz layout algorithm has rearranged the (ideal) order "wf2-> wz2 -> wa1 -> wx3" to "wx3, wf2, wz2, wa1". Therefore, my problem is:
My Problem: How to enforce the left-to-right node ordering in the rank environment?
With exploring in this site, I have found some similar problems and potential solutions. However, they just did not work in my specific example:
Graphviz .dot node ordering: the constraint = false option made my PDF picture worse. I checked the dot User's Manual which says:
During rank assignment, the head node of an edge is constrained to be on a higher rank than the tail node. If the edge has constraint=false, however, this requirement is not enforced.
Based on the above statements, (I guess) constraint = false option takes effect between different ranks instead of in the same rank.
Graphviz---random node order and edges going through labels: With surprise, the constraint = false option helped the "finite state machine" a lot in the same rank. Again, it does not save me from the trouble.
graphviz: circular layout while preserving node order: The process graph is dynamic both in number of nodes and edges. So, it maybe not attractive to use the absolute position for nodes (to cause many edge crossing?).
Thanks for any suggestions. And executable code will be appreciated very much.
digraph G
{
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
0 -> 1 -> 2 -> 3 -> 4;
}
node [shape = box];
{
rank = same;
0->wy1->rf1->rc1->rz1->ry1->ra1->rb1->rx2 [color=white];
rankdir=LR;
}
{
rank = same;
1->wf1[color=white];
rankdir=LR
}
{
rank = same;
2->wx2->wc1[color=white];
rankdir=LR;
}
{
rank = same;
3->wf2->wz2->wx3->wa1[color=white];
rankdir=LR;
}
{
rank = same;
4->wz1->wy2->wx5->wb1[color=white];
rankdir=LR;
}
wy1 -> rf1;
rf1 -> rc1;
rc1 -> rz1;
rz1 -> ry1;
ry1 -> ra1;
ra1 -> rb1;
rb1 -> rx2;
wx2 -> wc1;
wf2 -> wz2;
wz2 -> wx3;
wx3 -> wa1;
wz1 -> wy2;
wy2 -> wx5;
wx5 -> wb1;
wf1 -> rf1[color = blue];
wc1 -> rc1[color = blue];
wz1 -> rz1[color = blue];
wy1 -> ry1[color = blue];
wa1 -> ra1[color = blue];
wb1 -> rb1[color = blue];
wx2 -> rx2[color = blue];
// W'WR Order:
wx3 -> wx2[style = dashed, color = red];
// W'WR Order:
wx5 -> wx2[style = dashed, color = red];
}
I am not quite sure that i've correctly got your problem, but try using this and comment please if it is what you want. I've added invisible edges for correct ranking of nodes and used rankdir to use left-right layout.
I am trying to use Spin Model Checker to modelcheck a Game between two objects (A and B). The objects move on a board, and each location is defined by its (x,y) coordinates. The two objects are supposed to not collide. I have three processes: init, A Model, B Model. I am model checking an ltl property: (liveness property to check if the two objects ever occupy same location)
ltl prop1 { [] (!(x_a == x_b) && !(y_a == y_b)) }
The error trail that I get is:
init -> A Model -> B Model -> init
However, I should not get an error trail (counterexample) based on the data that is shown: x_a=2, x_b=1, y_a=1, y_b=1.
Also the first init does go through all the lines of init process, but the second one only shows to the last line of it.
Also my A Model and B Model only consist of guards and actions in a 'do' block as shown below. However they are more complex and have if blocks on the right of '->'
active proctype AModel(){
do
:: someValue == 1 -> go North
:: someValue == 2 -> go South
:: someValue == 3 -> go East
:: someValue == 4 -> go West
:: else -> skip;
od
}
Do I need to put anything in an atomic block? The reason I am asking is that the line that the error trail is showing does not even go into the 'do' block, and it is just the first line of the two models.
EDIT:
The LTL property was wrong. I changed that to:
ltl prop1 { [] (!((x_a == x_b) && (y_a == y_b))) }
However, I am still getting the exact same error trail.
Your LTL property is wrongly implemented. Essentially, the counter example that SPIN found is a true counter example for the LTL as stated.
[] ( !(x_a == x_b) && !(y_z == y_b) ) =>
[] ( !(2 == 1) && !(1 == 1) ) =>
[] ( !0 && !1) =>
[] ( 1 && 0) =>
[] 0 =>
false
The LTL should be:
always not (same location) =>
[] (! ((x_a == x_b) && (y_a == y_b))) =>
[] (! ((2 == 1) && (1 == 1))) =>
[] (! (0 && 1) =>
[] (! 0) =>
[] 1 =>
true
Regarding your init and tasks. When starting your tasks you want to be sure that initialization is complete before the tasks run. I'll use one of two approaches:
init { ... atomic { run taskA(); run taskB() } where tasks are spawned once all initialization is complete`
or
bool init_complete = false;
init { ...; init_complete = true }
proctype taskA () { /* init local stuff */ ...; init-complete -> /* begin real works */ ... }
Your LTL may be failing during the initialization.
And based on your problem, if you ever change x or y you'd better change both at once in an atomic{}.
I am just learning F# and have been converting a library of C# extension methods to F#. I am currently working on implementing a function called ConvertFirstLetterToUppercase based on the C# implementation below:
public static string ConvertFirstLetterToUppercase(this string value) {
if (string.IsNullOrEmpty(value)) return value;
if (value.Length == 1) return value.ToUpper();
return value.Substring(0, 1).ToUpper() + value.Substring(1);
}
The F# implementation
[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public StringHelper
open System
open System.Collections.Generic
open System.Linq
let ConvertHelper (x : char[]) =
match x with
| [| |] | null -> ""
| [| head; |] -> Char.ToUpper(head).ToString()
| [| head; _ |] -> Char.ToUpper(head).ToString() + string(x.Skip(1).ToArray())
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let ConvertFirstLetterToUppercase (_this : string) =
match _this with
| "" | null -> _this
| _ -> ConvertHelper (_this.ToCharArray())
Can someone show me a more concise implementation utilizing more natural F# syntax?
open System
type System.String with
member this.ConvertFirstLetterToUpperCase() =
match this with
| null -> null
| "" -> ""
| s -> s.[0..0].ToUpper() + s.[1..]
Usage:
> "juliet".ConvertFirstLetterToUpperCase();;
val it : string = "Juliet"
Something like this?
[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public StringHelper =
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let ConvertFirstLetterToUppercase (t : string) =
match t.ToCharArray() with
| null -> t
| [||] -> t
| x -> x.[0] <- Char.ToUpper(x.[0]); System.String(x)
Try the following
[<System.Runtime.CompilerServices.ExtensionAttribute>]
module StringExtensions =
let ConvertFirstLetterToUpperCase (data:string) =
match Seq.tryFind (fun _ -> true) data with
| None -> data
| Some(c) -> System.Char.ToUpper(c).ToString() + data.Substring(1)
The tryFind function will return the first element for which the lambda returns true. Since it always returns true it will simply return the first element or None. Once you've established there is at least one element you know data is not null and hence can call Substring
There's nothing wrong with using .NET library functions from a .NET language. Maybe a direct translation of your C# extension method is most appropriate, particularly for such a simple function. Although I'd be tempted to use the slicing syntax like Juliet does, just because it's cool.
open System
open System.Runtime.CompilerServices
[<Extension>]
module public StringHelper =
[<Extension>]
let ConvertFirstLetterToUpperCase(this:string) =
if String.IsNullOrEmpty this then this
elif this.Length = 1 then this.ToUpper()
else this.[0..0].ToUpper() + this.[1..]