- Joined
- Jun 15, 2017
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Sounds similar to a game called Dominions but I haven't played either.What really sets CoE apart to my mind is the amount of real historical / mythological detail in the different factions. Necromancers make use of hands of glory which are a real-life would-be magical item. The Priest King faction, like I said, is based on Mesoamerican lore and plays fast and loose with some details but overall there's decent correspondence with actual Aztec or Mayan beliefs. There's another faction called Cloud Lords whose names sounded to me kind of Indian or Persian and I found out they were Avestan names, which is an ancient Persian language. As it turns out, there are actual Persian legends about winged people with questionable morals, like in the game. There's a Demonologist faction where, if you try hard enough, you can even summon characters like in Dante's Inferno such as Geryon, Monster of Fraud. There are Lovecraftian entities too from the Void, made use of by the High Cultist faction, as if all of the other things weren't enough. You can bring gods into the world and kill opponent gods too. A smaller but still funny detail is this game is made by Scandinavians and moose, bears, deer and even fish-people who can be killed and smoked to feed entire villages are a constant low-level menace. These are the sorts of things that make CoE really worth playing from the days of the Atari ST up to the days of Steam in the current year.
Same devs. Conquest of Elysium is, roughly speaking, single-player Dominions.Sounds similar to a game called Dominions but I haven't played either.
Anytime I tried to plan for something I had no experience doing it was wasted effort.Ive done several coding projects over the past year but the one I've recently taken on has a wider scope than anything I've done before. Im determined to see it through and have something impressive for my portfolio and I decided I need to come up with a game plan.
Can somebody tell me how you would recommend planning out a large project for coding? I have a lot of ideas and I was thinking about taking the time to organize them and plan them out before I write any more code so I can work more efficiently.
To expand on this a bit, it helps to look for things that could reasonably be handled by a third-party library, even if you intend to write it yourself and don't intend to reuse the code elsewhere. That way you have a smaller, almost self-contained subproject you can start and experiment with more quickly. It also often encourages a cleaner design because there's less temptation towards dirty hacks that break the abstraction of your pretend library.I would recommend writing list of high level design goals, choosing one of it and splitting it in few tasks. Not too many though, even one will probably be enough.
One of the most important approaches is to get something running quickly. Don't build abstractions and classes and whatever you have without running compile, having a small program that runs even if it does nothing yet is the perfect starting point to change slowly into what you want it to do.Can somebody tell me how you would recommend planning out a large project for coding? I have a lot of ideas and I was thinking about taking the time to organize them and plan them out before I write any more code so I can work more efficiently.
it helps to look for things that could reasonably be handled by a third-party library, even if you intend to write it yourself and don't intend to reuse the code elsewhere.
Can I get a C++ tip from any passing 400-pound C whales?
In Windows, you can say "wait for a certain object to become signaled, or until X milliseconds pass", by simply:WaitForSingleObject(handle, msecWait);
Which you've been able to do since approximately the Jurassic period.
What's the best way of doing the same in modern C++ using the std::thread library?
The most obvious analog, using astd::condition_variable
, seems like a hack.
(example: https://en.cppreference.com/w/cpp/thread/stop_callback)
I've also seen suggestions of using astd::future
that you can either wait for or have it return early if "signaled".
std::condition_variable
is a hack; from my Linux-programmer perspective condvars are the first thing that come to mind.This is the Windows flavor of OS metaphor.wait for a certain object to become signaled, or until X milliseconds pass
This is the UNIX flavor of OS metaphor: poll(), select(), et cetera. This does not use the std:: namespace as you requested, but perhaps you'd rather use OS primitives instead of language primitives. See https://daniel.haxx.se/docs/poll-vs-select.html for more.UNIX flavor said:wait for an fd ready to read, or until X milliseconds pass
std::condition_variable
is implemented by a "futex", which is a sort of mutex that only does a syscall if it absolutely needs to. Even if it's trickier to use, it should be faster than doing the raw syscalls poll/epoll/select (on Linux) or WaitForSingleObject (on Windows).Yes! These old APIs are compatible but slow. io_uring ( https://en.wikipedia.org/wiki/Io_uring ) is liable to be the most performant from a syscall angle, and if you can avoid the syscalls (eg. futex), that's yet faster.faster than doing the raw syscalls poll/epoll/select (on Linux)
My advice is to sit down and figure out what you need to make a minimum viable product. Then determine how much of what you need can be provided by OSS projects. Think for a day or two and figure out how to sow things together, and then start. You may also want to look into your cloud provider, and figure them out first.Ive done several coding projects over the past year but the one I've recently taken on has a wider scope than anything I've done before. Im determined to see it through and have something impressive for my portfolio and I decided I need to come up with a game plan.
Can somebody tell me how you would recommend planning out a large project for coding? I have a lot of ideas and I was thinking about taking the time to organize them and plan them out before I write any more code so I can work more efficiently.
My current project is C# and doesnt involve internet but Im planning on upgrading my computer soon and setting up a personal website and back end server as my next big project.My advice is to sit down and figure out what you need to make a minimum viable product. Then determine how much of what you need can be provided by OSS projects. Think for a day or two and figure out how to sow things together, and then start. You may also want to look into your cloud provider, and figure them out first.
[URL='https://ocaml.org/p/domainslib/latest/doc/Domainslib/Chan/index.html']Chan.t[/URL]
where basic commands like Exit
or BlockSource
can be fed into the task. The tasks only poll, they don't block, on the command channel.let run task =
let running = ref true in
let rec handle_events () =
let handle_event event =
(* handle the event here *)
in
match Chan.recv_poll t.ingress_events with
| Some event ->
handle_event event;
handle_events ()
| None ->
()
in
let stream_single_pass () =
(* read something from task.source and then write it to task.sink *)
(* btw this function does block for a period of time if nothing's available *)
in
while Ref.(running.contents) do
handle_events ();
stream_single_pass ()
done;
()
utop # let my_mutable_variable = ref 3;;
val my_mutable_variable : int ref = {contents = 3}
utop # !my_mutable_variable;;
- : int = 3
utop # my_mutable_variable := 4;;
- : unit = ()
utop # !my_mutable_variable;;
- : int = 4
!
. The assignment operator isn't so bad, :=
, but using !
is super confusing if you're using the reference cell for a boolean variable.!
, I just looked at how ref is implemented in the standard library. It's actually a structure with a single mutable element called contents
.Ref.(running.contents)
instead. Far more readable.The point is that while the Internet offers the potential of massively connected code, the reality is that this is out of reach for most of us, and so large interesting problems (in health, education, economics, transport, and so on) remain unsolved because there is no way to connect the code, and thus no way to connect the brains that could work together to solve these problems.
There have been many attempts to solve the challenge of connected code. There are thousands of IETF specifications, each solving part of the puzzle. For application developers, HTTP is perhaps the one solution to have been simple enough to work, but it arguably makes the problem worse by encouraging developers and architects to think in terms of big servers and thin, stupid clients.
So today people are still connecting applications using raw UDP and TCP, proprietary protocols, HTTP, and Websockets. It remains painful, slow, hard to scale, and essentially centralized. Distributed P2P architectures are mostly for play, not work. How many applications use Skype or Bittorrent to exchange data?
Which brings us back to the science of programming. To fix the world, we needed to do two things. One, to solve the general problem of “how to connect any code to any code, anywhere”. Two, to wrap that up in the simplest possible building blocks that people could understand and use easily.
open Core
type stream = {
index : int
; name : string
} [@@deriving bin_io]
type frame_metadata = {
src : stream
; dst : stream
; payload_length : int
} [@@deriving bin_io]
type stream = { index : int; name : string; }
val bin_shape_stream : Bin_shape.t
val bin_size_stream : stream Bin_prot.Size.sizer
val bin_write_stream : stream Bin_prot.Write.writer
val bin_writer_stream : stream Bin_prot.Type_class.writer0
val __bin_read_stream__ : (int -> stream) Bin_prot.Read.reader
val bin_read_stream : stream Bin_prot.Read.reader
val bin_reader_stream : stream Bin_prot.Type_class.reader0
val bin_stream : stream Bin_prot.Type_class.t0
type frame_metadata = { src : stream; dst : stream; payload_length : int; }
val bin_shape_frame_metadata : Bin_shape.t
val bin_size_frame_metadata : frame_metadata Bin_prot.Size.sizer
val bin_write_frame_metadata : frame_metadata Bin_prot.Write.writer
val bin_writer_frame_metadata : frame_metadata Bin_prot.Type_class.writer0
val __bin_read_frame_metadata__ :
(int -> frame_metadata) Bin_prot.Read.reader
val bin_read_frame_metadata : frame_metadata Bin_prot.Read.reader
val bin_reader_frame_metadata : frame_metadata Bin_prot.Type_class.reader0
val bin_frame_metadata : frame_metadata Bin_prot.Type_class.t0
bin_read_frame_metadata
, bin_write_frame_metadata
and a bin_size_frame_metadata
.open Core
type stream = {
index : int
; name : string
} [@@deriving bin_io]
type frame_metadata = {
uuid : Uuidm.t
; src : stream
; dst : stream
; payload_length : int
} [@@deriving bin_io]
# #mod_use "/tmp/uuid_sample.ml";;
File "/tmp/uuid_sample.ml", line 11, characters 11-18:
11 | uuid : Uuidm.t
^^^^^^^
Error: Unbound value Uuidm.bin_shape_t
module Uuidm = struct
include Uuidm
let bin_shape_t = bin_shape_bytes
let bin_size_t uuidm =
Uuidm.to_binary_string uuidm
|> Bytes.of_string
|> bin_size_bytes
let bin_write_t buf ~pos uuidm =
Uuidm.to_binary_string uuidm
|> Bytes.of_string
|> bin_write_bytes buf ~pos
let bin_read_t buf ~pos_ref =
bin_read_bytes buf ~pos_ref
|> Bytes.to_string
|> Uuidm.of_binary_string
|> Option.value_exn
end
Uuidm.to_binary_string
function (produces something that looks like "²³G\014\002K\000²\021/_x·5R"
) and then passed it to the built-in byte readers+writers.open Core
is. The Core library is basically a private overlay that adds a lot of useful features to the standard library. Tbf, the standard Ocaml library is kinda limp. It was only really meant to bootstrap the compiler, so for most practical work, you'll want to incorporate something like Core.package media_lib.messages;
syntax = "proto3";
message Stream {
int32 index = 1;
string name = 2;
}
message FrameMetadata {
Stream src = 1;
Stream dst = 2;
int32 payload_length = 3;
}
failwith "todo finish this function"
.No homo but this post is great literature, even though (because?) I understand like two words per sentence. In a hundred years, a historical fantasy novelist is going to copypaste it wholesale into his novel entitled "Seventeen Ways to Defend a Firewalled Server".In the meanwhile... I'm back to working on my little personal project. (First post, second post, third post)
I can't wait for the literary analysis. The first phd paper about it in Autistic English Literature will be off the chain.No homo but this post is great literature, even though (because?) I understand like two words per sentence. In a hundred years, a historical fantasy novelist is going to copypaste it wholesale into his novel entitled "Seventeen Ways to Defend a Firewalled Server".
I can agree on the fact that having two separate functions for splitting strings starting from different directions is better for Python specifically: consider that people that program in Python are either beginner programmers or experts that need some quick scripts where clarity is preferred instead of "clever code".-snip-
split_from_left
and split_from_right
let you immediately understand what they do instead of having split
and rsplit
.