codingteam / hyperspace Goto Github PK
View Code? Open in Web Editor NEWSimple 2D game written in Clojure and Kotlin.
License: MIT License
Simple 2D game written in Clojure and Kotlin.
License: MIT License
I obviously don't know how to write network games. And I don't know how to write games at all.
That's the reason of current state of the project. Here's the list of things I thought were nice to have and tried to implement them:
And here's the list of the successfully-implemented features:
(It's an empty list)
So, with all the today's experience and the knowledge that the failed non-working project is very hard to resurrect we need to make a new plan for the project. Main questions about the further project development:
Do we need a network server, or could it be a single-player game?
If we want a network game, then how should it work? Need a bit of game design docs (or at least a concept at the moment).
What minimal steps we should take to put the project back into the working state?
How should we organize the development to avoid project destabilization in future? (E.g. make a smooth migration from client-only to client-server architecture etc.)
Guys, please help me to plan the future.
Based on the current project state and its historical value (see #27), I propose the following.
Hyperspace should be a network multiplayer game for now designed for two players. It should consist of dedicated server application and a client application, both written in Clojure. Also, there should be a shared library of physical simulation functions used both by the client and the server code.
Hyperspace is a turn-based physic simulator game. There're two players and a number of planets on the game field. Each player shoot a missile during each turn (but he could choose to skip the turn; that could also happen due to turn timeout); missiles behave as a bodies of mass in a static environment with Newtonian physics. Only missiles and planets have mass; missiles, planets and players also have a collision radius that should be taken into account by the simulation.
If the player is hit by enemy's missile, he's dead. If the missile hits the planet surface, then the missile explodes. If the missile hits the game world boundaries, it's considered "lost".
Player controls the shot power (in some diapason allowed by server) and direction.
The player turns are performed simultaneously. If both of the players are hit by enemy missiles at the same turn, the game is a tie.
Server should provide HTTP API capable of:
When joining the game, server sends to the client a game key that should be used to schedule turns and query the game state.
When scheduling a turn, each client sends to the server their shot power and direction parameters.
When all the players in a game have been scheduled their turns, server simultaneously performs the turns.
When the client queries the game state, server sends the game map and the shot/direction history for each player. Shot information also contains a coordinates where the shot has been exploded and information whether any of players was hit by the collision.
Each game should have a round timeout. If any of the clients haven't scheduled their turn in time, their shooting phase should be skipped.
Client is a desktop application. It should have two windows:
The game client should calculate the trajectory itself using the same library as the server, and render the missile at its way to the target. But it should respect server decisions on whether any of the players was hit by the bullet, and show the point where the server reported a bullet collision. (In general, server and client calculations should be almost the same, but they could differ due to floating point arithmetic; server obviously always have the priority in case of any desyncronization.)
osx10.9, java7/8
$ lein run
JavaVM WARNING: JAWT_GetAWT must be called after loading a JVM
Exception in thread "main" org.lwjgl.LWJGLException: Could not get the JAWT interface
at org.lwjgl.opengl.AWTSurfaceLock.lockAndInitHandle(Native Method)
at org.lwjgl.opengl.AWTSurfaceLock.access$100(AWTSurfaceLock.java:51)
at org.lwjgl.opengl.AWTSurfaceLock$1.run(AWTSurfaceLock.java:94)
at org.lwjgl.opengl.AWTSurfaceLock$1.run(AWTSurfaceLock.java:92)
at java.security.AccessController.doPrivileged(Native Method)
at org.lwjgl.opengl.AWTSurfaceLock.privilegedLockAndInitHandle(AWTSurfaceLock.java:92)
at org.lwjgl.opengl.AWTSurfaceLock.lockAndGetHandle(AWTSurfaceLock.java:66)
at org.lwjgl.opengl.MacOSXCanvasPeerInfo.initHandle(MacOSXCanvasPeerInfo.java:57)
at org.lwjgl.opengl.MacOSXDisplayPeerInfo.doLockAndInitHandle(MacOSXDisplayPeerInfo.java:56)
at org.lwjgl.opengl.PeerInfo.lockAndGetHandle(PeerInfo.java:85)
at org.lwjgl.opengl.MacOSXContextImplementation.create(MacOSXContextImplementation.java:47)
at org.lwjgl.opengl.ContextGL.<init>(ContextGL.java:132)
at org.lwjgl.opengl.Display.create(Display.java:847)
at org.lwjgl.opengl.Display.create(Display.java:754)
at org.lwjgl.opengl.Display.create(Display.java:736)
at hyperspace.ui$setup_ui.invoke(ui.clj:124)
at hyperspace.ui$start_ui.invoke(ui.clj:154)
at hyperspace.main$_main.doInvoke(main.clj:7)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:411)
at user$eval672.invoke(form-init6915732820426289453.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6511)
at clojure.lang.Compiler.eval(Compiler.java:6501)
at clojure.lang.Compiler.load(Compiler.java:6952)
at clojure.lang.Compiler.loadFile(Compiler.java:6912)
at clojure.main$load_script.invoke(main.clj:283)
at clojure.main$init_opt.invoke(main.clj:288)
at clojure.main$initialize.invoke(main.clj:316)
at clojure.main$null_opt.invoke(main.clj:349)
at clojure.main$main.doInvoke(main.clj:427)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
See this:
Hyperspace/src/hyperspace/client/richworld.clj
Lines 39 to 48 in 91d0b6b
Implement network API for hyperspace. @hagane suggests that we should use Apache Thrift for that purpose.
We need an API for managing game-related information: creating new games, game listing and joining games.
Sometimes, the build on CI may be stuck. I think that we'll fix this by migrating from Clojurephant eventually.
I'm just filing this issue to not forget the situation. We have an ancient branch named clojurescript
, and it seems that it should have some outdated cljs stuff.
I think that it'll be eventually useful to write a client for Hyperspace in Clojurescript. That way, our players won't be forced to download the client, install the JVM etc.
But this task isn't planned for current iteration.
There are some midje tests (defined with facts
) that aren't executed for now.
I also cannot even run them because of java.io.FileNotFoundException: Could not locate hyperspace/server/main__init.class or hyperspace/server/main.clj on classpath
.
We'll need a database (classically we use H2) for user data storage.
"Slingshot" in Readme links to http://slingshot.wikispot.org/ , but this URL now redirects to localwiki.org.
(Excerpt from #29.)
Server should provide HTTP API capable of:
register a new game
query game list
join a game
schedule the game turn
query the state of the game
Each game should have a round timeout. If any of the clients haven't scheduled their turn in time, their shooting phase should be skipped.
We'll need a test client accessing our swagger API.
We need an API (and a database structure) for user registration and logging in.
Players need an API for planning the turns and getting the turn results. I will maybe break this task to multiple smaller tasks later.
This is required for clojurephant.
We need a compact way to present the bullet trajectory.
My research using differential equations does not seem to end with a great success, so maybe we need something more simple.
One example is presentation of current calculated trajectory as a group of Bezier curves.
$ lein run client
Exception in thread "main" java.lang.NullPointerException, compiling:(T:\Temp\form-init7564624643793564877.clj:1:78)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$init_opt.invokeStatic(main.clj:277)
at clojure.main$init_opt.invoke(main.clj:277)
at clojure.main$initialize.invokeStatic(main.clj:308)
at clojure.main$null_opt.invokeStatic(main.clj:342)
at clojure.main$null_opt.invoke(main.clj:339)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
at clojure.lang.Numbers.ops(Numbers.java:1013)
at clojure.lang.Numbers.multiply(Numbers.java:148)
at clojure.lang.Numbers.multiply(Numbers.java:3740)
at hyperspace.client.ui$render_player.invokeStatic(ui.clj:98)
at hyperspace.client.ui$render_player.invoke(ui.clj:88)
at hyperspace.client.ui$render_world.invokeStatic(ui.clj:117)
at hyperspace.client.ui$render_world.invoke(ui.clj:105)
at hyperspace.client.ui$ui_loop.invokeStatic(ui.clj:148)
at hyperspace.client.ui$ui_loop.invoke(ui.clj:136)
at hyperspace.client.ui$start.invokeStatic(ui.clj:157)
at hyperspace.client.ui$start.invoke(ui.clj:154)
at hyperspace.client.main$run.invokeStatic(main.clj:6)
at hyperspace.client.main$run.doInvoke(main.clj:5)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.core$apply.invokeStatic(core.clj:646)
at clojure.core$apply.invoke(core.clj:641)
at hyperspace.main$_main.invokeStatic(main.clj:7)
at hyperspace.main$_main.doInvoke(main.clj:5)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at clojure.lang.Var.invoke(Var.java:379)
at user$eval5.invokeStatic(form-init7564624643793564877.clj:1)
at user$eval5.invoke(form-init7564624643793564877.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.eval(Compiler.java:6917)
at clojure.lang.Compiler.load(Compiler.java:7379)
... 14 more
While investigating #44, I've found that even if we fix the dependency issues, the server isn't able to work:
lein ring server
2021-08-19 23:05:25.001:INFO::main: Logging initialized @1177ms
WARNING: vector already refers to: #'clojure.core/vector in namespace: potemkin.utils, being replaced by: #'clj-tuple/vector
WARNING: hash-map already refers to: #'clojure.core/hash-map in namespace: potemkin.utils, being replaced by: #'clj-tuple/hash-map
Syntax error macroexpanding clojure.core/fn at (azql\expression.clj:209:1).
operator-/ - failed: vector? at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
operator-/ - failed: (or (nil? %) (sequential? %)) at: [:fn-tail :arity-n] spec: :clojure.core.specs.alpha/params+body
azql seems to cause some problems in macro expansion which prevents server from starting. For now, I had to disable the user server module because of that (#46).
We currently have some tests that are not working. We need to fix that somehow.
I think that probably some of them are testing some deprecated stuff and can be safely removed.
According to my current plans, this project should be able to build/test using Gradle.
Requires:
There's core.typed. It adds the type checking to Clojure code. I think that we have to use it.
All I get now is:
$ lein ring server
clojure.lang.Compiler$CompilerException: Syntax error macroexpanding clojure.core/fn at (clojure/core/unify.clj:83:18).
#:clojure.error{:phase :macro-syntax-check, :line 83, :column 18, :source "clojure/core/unify.clj", :symbol clojure.core/fn}
at clojure.lang.Compiler.checkSpecs (Compiler.java:6972)
clojure.lang.Compiler.macroexpand1 (Compiler.java:6988)
clojure.lang.Compiler.analyzeSeq (Compiler.java:7093)
clojure.lang.Compiler.analyze (Compiler.java:6789)
clojure.lang.Compiler.analyzeSeq (Compiler.java:7095)
clojure.lang.Compiler.analyze (Compiler.java:6789)
clojure.lang.Compiler.access$300 (Compiler.java:38)
clojure.lang.Compiler$DefExpr$Parser.parse (Compiler.java:596)
clojure.lang.Compiler.analyzeSeq (Compiler.java:7107)
clojure.lang.Compiler.analyze (Compiler.java:6789)
clojure.lang.Compiler.analyze (Compiler.java:6745)
clojure.lang.Compiler.eval (Compiler.java:7181)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:421)
clojure.core.contracts.impl.transformers$eval691$loading__6721__auto____692.invoke (transformers.clj:1)
clojure.core.contracts.impl.transformers$eval691.invokeStatic (transformers.clj:1)
clojure.core.contracts.impl.transformers$eval691.invoke (transformers.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:408)
leinjacker.defconstrainedfn$eval685$loading__6721__auto____686.invoke (defconstrainedfn.clj:1)
leinjacker.defconstrainedfn$eval685.invokeStatic (defconstrainedfn.clj:1)
leinjacker.defconstrainedfn$eval685.invoke (defconstrainedfn.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:669)
clojure.core$use.invokeStatic (core.clj:6093)
clojure.core$use.doInvoke (core.clj:6093)
clojure.lang.RestFn.invoke (RestFn.java:408)
leinjacker.deps$eval677$loading__6721__auto____678.invoke (deps.clj:1)
leinjacker.deps$eval677.invokeStatic (deps.clj:1)
leinjacker.deps$eval677.invoke (deps.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:436)
leiningen.ring.server$eval669$loading__6721__auto____670.invoke (server.clj:1)
leiningen.ring.server$eval669.invokeStatic (server.clj:1)
leiningen.ring.server$eval669.invoke (server.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:669)
clojure.core$use.invokeStatic (core.clj:6093)
clojure.core$use.doInvoke (core.clj:6093)
clojure.lang.RestFn.invoke (RestFn.java:551)
leiningen.ring$eval663$loading__6721__auto____664.invoke (ring.clj:1)
leiningen.ring$eval663.invokeStatic (ring.clj:1)
leiningen.ring$eval663.invoke (ring.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:408)
leiningen.core.utils$require_resolve.invokeStatic (utils.clj:102)
leiningen.core.utils$require_resolve.invoke (utils.clj:95)
leiningen.core.utils$require_resolve.invokeStatic (utils.clj:105)
leiningen.core.utils$require_resolve.invoke (utils.clj:95)
leiningen.core.main$lookup_task_var.invokeStatic (main.clj:69)
leiningen.core.main$lookup_task_var.invoke (main.clj:65)
leiningen.core.main$pass_through_help_QMARK_.invokeStatic (main.clj:79)
leiningen.core.main$pass_through_help_QMARK_.invoke (main.clj:73)
leiningen.core.main$task_args.invokeStatic (main.clj:82)
leiningen.core.main$task_args.invoke (main.clj:81)
leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:339)
leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
leiningen.core.main$_main$fn__7420.invoke (main.clj:453)
leiningen.core.main$_main.invokeStatic (main.clj:442)
leiningen.core.main$_main.doInvoke (main.clj:439)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.lang.Var.applyTo (Var.java:705)
clojure.core$apply.invokeStatic (core.clj:665)
clojure.main$main_opt.invokeStatic (main.clj:514)
clojure.main$main_opt.invoke (main.clj:510)
clojure.main$main.invokeStatic (main.clj:664)
clojure.main$main.doInvoke (main.clj:616)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.lang.Var.applyTo (Var.java:705)
clojure.main.main (main.java:40)
Caused by: clojure.lang.ExceptionInfo: Call to clojure.core/fn did not conform to spec.
#:clojure.spec.alpha{:problems ({:path [:fn-tail :arity-1 :params], :pred clojure.core/vector?, :val clojure.core.unify/var-unify, :via [:clojure.core.specs.alpha/params+body
:clojure.core.specs.alpha/param-list :clojure.core.specs.alpha/param-list], :in [0]} {:path [:fn-tail :arity-n], :pred (clojure.core/fn [%] (clojure.core/or (clojure.core/ni
l? %) (clojure.core/sequential? %))), :val clojure.core.unify/var-unify, :via [:clojure.core.specs.alpha/params+body :clojure.core.specs.alpha/params+body], :in [0]}), :spec
#object[clojure.spec.alpha$regex_spec_impl$reify__2509 0x2d5f7182 "clojure.spec.alpha$regex_spec_impl$reify__2509@2d5f7182"], :value (clojure.core.unify/var-unify [G__801 G__
802 G__803 G__804] (clojure.core/if-let [vb__794__auto__ (G__804 G__802)] (clojure.core.unify/garner-unifiers G__801 vb__794__auto__ G__803 G__804) (clojure.core/if-let [vexp
r__795__auto__ (clojure.core/and (G__801 G__803) (G__804 G__803))] (clojure.core.unify/garner-unifiers G__801 G__802 vexpr__795__auto__ G__804) (if (clojure.core.unify/occurs
? G__801 G__802 G__803 G__804) (throw (java.lang.IllegalStateException. (clojure.core/str "Cycle found in the path " G__803))) (clojure.core.unify/bind-phase G__804 G__802 G_
_803))))), :args (clojure.core.unify/var-unify [G__801 G__802 G__803 G__804] (clojure.core/if-let [vb__794__auto__ (G__804 G__802)] (clojure.core.unify/garner-unifiers G__801
vb__794__auto__ G__803 G__804) (clojure.core/if-let [vexpr__795__auto__ (clojure.core/and (G__801 G__803) (G__804 G__803))] (clojure.core.unify/garner-unifiers G__801 G__802
vexpr__795__auto__ G__804) (if (clojure.core.unify/occurs? G__801 G__802 G__803 G__804) (throw (java.lang.IllegalStateException. (clojure.core/str "Cycle found in the path "
G__803))) (clojure.core.unify/bind-phase G__804 G__802 G__803)))))}
at clojure.spec.alpha$macroexpand_check.invokeStatic (alpha.clj:705)
clojure.spec.alpha$macroexpand_check.invoke (alpha.clj:697)
clojure.lang.AFn.applyToHelper (AFn.java:156)
clojure.lang.AFn.applyTo (AFn.java:144)
clojure.lang.Var.applyTo (Var.java:705)
clojure.lang.Compiler.checkSpecs (Compiler.java:6970)
clojure.lang.Compiler.macroexpand1 (Compiler.java:6988)
clojure.lang.Compiler.analyzeSeq (Compiler.java:7093)
clojure.lang.Compiler.analyze (Compiler.java:6789)
clojure.lang.Compiler.analyzeSeq (Compiler.java:7095)
clojure.lang.Compiler.analyze (Compiler.java:6789)
clojure.lang.Compiler.access$300 (Compiler.java:38)
clojure.lang.Compiler$DefExpr$Parser.parse (Compiler.java:596)
clojure.lang.Compiler.analyzeSeq (Compiler.java:7107)
clojure.lang.Compiler.analyze (Compiler.java:6789)
clojure.lang.Compiler.analyze (Compiler.java:6745)
clojure.lang.Compiler.eval (Compiler.java:7181)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:421)
clojure.core.contracts.impl.transformers$eval691$loading__6721__auto____692.invoke (transformers.clj:1)
clojure.core.contracts.impl.transformers$eval691.invokeStatic (transformers.clj:1)
clojure.core.contracts.impl.transformers$eval691.invoke (transformers.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:408)
leinjacker.defconstrainedfn$eval685$loading__6721__auto____686.invoke (defconstrainedfn.clj:1)
leinjacker.defconstrainedfn$eval685.invokeStatic (defconstrainedfn.clj:1)
leinjacker.defconstrainedfn$eval685.invoke (defconstrainedfn.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:669)
clojure.core$use.invokeStatic (core.clj:6093)
clojure.core$use.doInvoke (core.clj:6093)
clojure.lang.RestFn.invoke (RestFn.java:408)
leinjacker.deps$eval677$loading__6721__auto____678.invoke (deps.clj:1)
leinjacker.deps$eval677.invokeStatic (deps.clj:1)
leinjacker.deps$eval677.invoke (deps.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:436)
leiningen.ring.server$eval669$loading__6721__auto____670.invoke (server.clj:1)
leiningen.ring.server$eval669.invokeStatic (server.clj:1)
leiningen.ring.server$eval669.invoke (server.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:669)
clojure.core$use.invokeStatic (core.clj:6093)
clojure.core$use.doInvoke (core.clj:6093)
clojure.lang.RestFn.invoke (RestFn.java:551)
leiningen.ring$eval663$loading__6721__auto____664.invoke (ring.clj:1)
leiningen.ring$eval663.invokeStatic (ring.clj:1)
leiningen.ring$eval663.invoke (ring.clj:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7166)
clojure.lang.Compiler.load (Compiler.java:7636)
clojure.lang.RT.loadResourceScript (RT.java:381)
clojure.lang.RT.loadResourceScript (RT.java:372)
clojure.lang.RT.load (RT.java:459)
clojure.lang.RT.load (RT.java:424)
clojure.core$load$fn__6839.invoke (core.clj:6126)
clojure.core$load.invokeStatic (core.clj:6125)
clojure.core$load.doInvoke (core.clj:6109)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.core$load_one.invokeStatic (core.clj:5908)
clojure.core$load_one.invoke (core.clj:5903)
clojure.core$load_lib$fn__6780.invoke (core.clj:5948)
clojure.core$load_lib.invokeStatic (core.clj:5947)
clojure.core$load_lib.doInvoke (core.clj:5928)
clojure.lang.RestFn.applyTo (RestFn.java:142)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$load_libs.invokeStatic (core.clj:5985)
clojure.core$load_libs.doInvoke (core.clj:5969)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.core$apply.invokeStatic (core.clj:667)
clojure.core$require.invokeStatic (core.clj:6007)
clojure.core$require.doInvoke (core.clj:6007)
clojure.lang.RestFn.invoke (RestFn.java:408)
leiningen.core.utils$require_resolve.invokeStatic (utils.clj:102)
leiningen.core.utils$require_resolve.invoke (utils.clj:95)
leiningen.core.utils$require_resolve.invokeStatic (utils.clj:105)
leiningen.core.utils$require_resolve.invoke (utils.clj:95)
leiningen.core.main$lookup_task_var.invokeStatic (main.clj:69)
leiningen.core.main$lookup_task_var.invoke (main.clj:65)
leiningen.core.main$pass_through_help_QMARK_.invokeStatic (main.clj:79)
leiningen.core.main$pass_through_help_QMARK_.invoke (main.clj:73)
leiningen.core.main$task_args.invokeStatic (main.clj:82)
leiningen.core.main$task_args.invoke (main.clj:81)
leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:339)
leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
leiningen.core.main$_main$fn__7420.invoke (main.clj:453)
leiningen.core.main$_main.invokeStatic (main.clj:442)
leiningen.core.main$_main.doInvoke (main.clj:439)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.lang.Var.applyTo (Var.java:705)
clojure.core$apply.invokeStatic (core.clj:665)
clojure.main$main_opt.invokeStatic (main.clj:514)
clojure.main$main_opt.invoke (main.clj:510)
clojure.main$main.invokeStatic (main.clj:664)
clojure.main$main.doInvoke (main.clj:616)
clojure.lang.RestFn.applyTo (RestFn.java:137)
clojure.lang.Var.applyTo (Var.java:705)
clojure.main.main (main.java:40)
We need to integrate thrift
into our build process. Some useful tools are probably thriftrc for automatic compilation and thrift-clj for type importing.
We need the main API for making turns and accessing turn/game results.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.