Fatshark’s co-op Ogryn party simulator Warhammer 40,000: Darktide has been in preorder beta for just under a week, and in that time players have been pointing out various issues. Chief among those issues: crashes. While I’ve been lucky enough to only have Darktide crash on me twice, plenty of others have found it to be less stable. 

The patch notes (opens in new tab) for version 1.0.7 identify six different types of crashes that have now been purged: matchmaking crashes, cutscene alt-tabbing crashes, falling-out-of-bounds crashes, crashes caused by starting a mission with a specific feat equipped, crashes caused by certain weapon traits, and multiple crashes caused by the Beast of Nurgle. As if we didn’t have enough reasons to hate Beasts of Nurgle already.



Source link

Crystal Dynamics says Marvel’s Avengers design lead Brian Waggoner “will no longer be a studio spokesperson” or speak publicly about its projects after offensive tweets he’d previously posted were brought to light by the community.

Posted over a period of years stretching at least as far back as 2011, the tweets in question were variously racist, ableist, and homophobic: Not egregiously hateful, but plentiful, and most of them reflecting basic right-wing talking points like black-on-black crime (opens in new tab) or US President Barack Obama’s citizenship (opens in new tab). Most of the tweets have since been deleted, but in a 2020 tweet that’s still posted Waggoner described himself as a “Trump voter (opens in new tab).”



Source link

Playing PC games on the move is an attractive proposition, and now is a decent time to buy a gaming laptop. Nvidia’s new mid-range RTX 40-series desktop GPUs will be here early next year, but its 40-series laptop GPUs won’t be available until sometime later, so an RTX 30-series mobile chip shouldn’t immediately feel out-of-date. (Don’t bother with an RTX 20-series laptop at this point, though.) This is also the time of year when everything goes on sale, starting with Black Friday and Cyber Monday.

In anticipation of the sales and gift giving season, we’ve collected some of our favorite gaming laptops here. This article was produced with support from Intel. We like Intel’s mobile CPUs and the laptops we’ve selected here include them, but for more recommendations, including some AMD builds, see our guide to the best gaming laptops. This list includes a larger variety of laptops, all with specs that we favor—enough memory and SSD storage to be viable gaming machines, good screens with refresh rates as high as 360Hz, and good graphics processors to drive them. 



Source link

Warhammer: Vermintide 2 veterans know that every successful run demands picking up two ominous grimoires and three well-hidden tomes, secret items that reward you with far better loot drops at the end of a successful mission. They also amp up the challenge, taking up vital inventory space and reducing your health pool to a risky sliver. We expected grimoires and tomes to be back in Warhammer 40K: Darktide, and they are—but with some significant changes.

Tomes have been renamed to “scriptures,” and Darktide’s reworked loot system means the reward for finding grimoires and tomes is a bit different, this time around. The biggest change, though, is that as best as we can tell so far, grimoires and scriptures are no longer in the same place in each level.



Source link


Cyberpower’s GXi4700W gaming PC is the only Black Friday discounted rig that doesn’t look like every other colorless box out there. You do want your computer to be Instagrammable, right? Walmart has knocked $300 off of it, bringing it to a budget-friendly $899 (opens in new tab).

Sometimes you have to risk it all for an aesthetic. The airflow in the $899 Cyberpower GXi4700W gaming PC looks a little suspect, but a number of Best Buy reviews (opens in new tab) for a separate PC with the case express that it’s not a problem. There aren’t any retail reviews for this exact configuration, but some Reddit comments say it’s not as bad as it looks.



Source link


Do you feel the need for speed? More importantly, does your PC have the speed to make the new Need for Speed run with the speed you need? Today is the day to find out.

Need for Speed Unbound (opens in new tab) is set to launch on December 2, and with that date now just over a week away, Electronic Arts has dropped details (opens in new tab) on when exactly it will launch, what sort of accessibility options it will support, and—as promised above, what exactly you’ll need to run it.



Source link


Luau is the first programming language to put the power of semantic subtyping in the hands of millions of creators.

Minimizing false positives

One of the issues with type error reporting in tools like the Script Analysis widget in Roblox Studio is false positives. These are warnings that are artifacts of the analysis, and don’t correspond to errors which can occur at runtime. For example, the program

local x = CFrame.new()
local y
if (math.random()) then
  y = CFrame.new()
else
  y = Vector3.new()
end
local z = x * y

reports a type error which cannot happen at runtime, since CFrame supports multiplication by both Vector3 and CFrame. (Its type is ((CFrame, CFrame) -> CFrame) & ((CFrame, Vector3) -> Vector3).)

False positives are especially poor for onboarding new users. If a type-curious creator switches on typechecking and is immediately faced with a wall of spurious red squiggles, there is a strong incentive to immediately switch it off again.

Inaccuracies in type errors are inevitable, since it is impossible to decide ahead of time whether a runtime error will be triggered. Type system designers have to choose whether to live with false positives or false negatives. In Luau this is determined by the mode: strict mode errs on the side of false positives, and nonstrict mode errs on the side of false negatives.

While inaccuracies are inevitable, we try to remove them whenever possible, since they result in spurious errors, and imprecision in type-driven tooling like autocomplete or API documentation.

Subtyping as a source of false positives

One of the sources of false positives in Luau (and many other similar languages like TypeScript or Flow) is subtyping. Subtyping is used whenever a variable is initialized or assigned to, and whenever a function is called: the type system checks that the type of the expression is a subtype of the type of the variable. For example, if we add types to the above program

local x : CFrame = CFrame.new()
local y : Vector3 | CFrame
if (math.random()) then
  y = CFrame.new()
else
  y = Vector3.new()
end
local z : Vector3 | CFrame = x * y

then the type system checks that the type of CFrame multiplication is a subtype of (CFrame, Vector3 | CFrame) -> (Vector3 | CFrame).

Subtyping is a very useful feature, and it supports rich type constructs like type union (T | U) and intersection (T & U). For example, number? is implemented as a union type (number | nil), inhabited by values that are either numbers or nil.

Unfortunately, the interaction of subtyping with intersection and union types can have odd results. A simple (but rather artificial) case in older Luau was:

local x : (number?) & (string?) = nil
local y : nil = nil
y = x -- Type '(number?) & (string?)' could not be converted into 'nil'
x = y

This error is caused by a failure of subtyping, the old subtyping algorithm reports that (number?) & (string?) is not a subtype of nil. This is a false positive, since number & string is uninhabited, so the only possible inhabitant of (number?) & (string?) is nil.

This is an artificial example, but there are real issues raised by creators caused by the problems, for example https://devforum.roblox.com/t/luau-recap-july-2021/1382101/5. Currently, these issues mostly affect creators making use of sophisticated type system features, but as we make type inference more accurate, union and intersection types will become more common, even in code with no type annotations.

This class of false positives no longer occurs in Luau, as we have moved from our old approach of syntactic subtyping to an alternative called semantic subtyping.

Syntactic subtyping

AKA “what we did before.”

Syntactic subtyping is a syntax-directed recursive algorithm. The interesting cases to deal with intersection and union types are:

  • Reflexivity: T is a subtype of T
  • Intersection L: (T₁ & … & Tⱼ) is a subtype of U whenever some of the Tᵢ are subtypes of U
  • Union L: (T₁ | … | Tⱼ) is a subtype of U whenever all of the Tᵢ are subtypes of U
  • Intersection R: T is a subtype of (U₁ & … & Uⱼ) whenever T is a subtype of all of the Uᵢ
  • Union R: T is a subtype of (U₁ | … | Uⱼ) whenever T is a subtype of some of the Uᵢ.

For example:

  • By Reflexivity: nil is a subtype of nil
  • so by Union R: nil is a subtype of number?
  • and: nil is a subtype of string?
  • so by Intersection R: nil is a subtype of (number?) & (string?).

Yay! Unfortunately, using these rules:

  • number isn’t a subtype of nil
  • so by Union L: (number?) isn’t a subtype of nil
  • and: string isn’t a subtype of nil
  • so by Union L: (string?) isn’t a subtype of nil
  • so by Intersection L: (number?) & (string?) isn’t a subtype of nil.

This is typical of syntactic subtyping: when it returns a “yes” result, it is correct, but when it returns a “no” result, it might be wrong. The algorithm is a conservative approximation, and since a “no” result can lead to type errors, this is a source of false positives.

Semantic subtyping

AKA “what we do now.”

Rather than thinking of subtyping as being syntax-directed, we first consider its semantics, and later return to how the semantics is implemented. For this, we adopt semantic subtyping:

  • The semantics of a type is a set of values.
  • Intersection types are thought of as intersections of sets.
  • Union types are thought of as unions of sets.
  • Subtyping is thought of as set inclusion.

For example:

Type Semantics
number { 1, 2, 3, … }
string { “foo”, “bar”, … }
nil { nil }
number? { nil, 1, 2, 3, … }
string? { nil, “foo”, “bar”, … }
(number?) & (string?) { nil, 1, 2, 3, … } ∩ { nil, “foo”, “bar”, … } = { nil }

and since subtypes are interpreted as set inclusions:

Subtype Supertype Because
nil number? { nil } ⊆ { nil, 1, 2, 3, … }
nil string? { nil } ⊆ { nil, “foo”, “bar”, … }
nil (number?) & (string?) { nil } ⊆ { nil }
(number?) & (string?) nil { nil } ⊆ { nil }

So according to semantic subtyping, (number?) & (string?) is equivalent to nil, but syntactic subtyping only supports one direction.

This is all fine and good, but if we want to use semantic subtyping in tools, we need an algorithm, and it turns out checking semantic subtyping is non-trivial.

Semantic subtyping is hard

NP-hard to be precise.

We can reduce graph coloring to semantic subtyping by coding up a graph as a Luau type such that checking subtyping on types has the same result as checking for the impossibility of coloring the graph

For example, coloring a three-node, two color graph can be done using types:

type Red = "red"
type Blue = "blue"
type Color = Red | Blue
type Coloring = (Color) -> (Color) -> (Color) -> boolean
type Uncolorable = (Color) -> (Color) -> (Color) -> false

Then a graph can be encoded as an overload function type with subtype Uncolorable and supertype Coloring, as an overloaded function which returns false when a constraint is violated. Each overload encodes one constraint. For example a line has constraints saying that adjacent nodes cannot have the same color:

type Line = Coloring
  & ((Red) -> (Red) -> (Color) -> false)
  & ((Blue) -> (Blue) -> (Color) -> false)
  & ((Color) -> (Red) -> (Red) -> false)
  & ((Color) -> (Blue) -> (Blue) -> false)

A triangle is similar, but the end points also cannot have the same color:

type Triangle = Line
  & ((Red) -> (Color) -> (Red) -> false)
  & ((Blue) -> (Color) -> (Blue) -> false)

Now, Triangle is a subtype of Uncolorable, but Line is not, since the line can be 2-colored. This can be generalized to any finite graph with any finite number of colors, and so subtype checking is NP-hard.

We deal with this in two ways:

  • we cache types to reduce memory footprint, and
  • give up with a “Code Too Complex” error if the cache of types gets too large.

Hopefully this doesn’t come up in practice much. There is good evidence that issues like this don’t arise in practice from experience with type systems like that of Standard ML, which is EXPTIME-complete, but in practice you have to go out of your way to code up Turing Machine tapes as types.

Type normalization

The algorithm used to decide semantic subtyping is type normalization. Rather than being directed by syntax, we first rewrite types to be normalized, then check subtyping on normalized types.

A normalized type is a union of:

  • a normalized nil type (either never or nil)
  • a normalized number type (either never or number)
  • a normalized boolean type (either never or true or false or boolean)
  • a normalized function type (either never or an intersection of function types) etc

Once types are normalized, it is straightforward to check semantic subtyping.

Every type can be normalized (sigh, with some technical restrictions around generic type packs). The important steps are:

  • removing intersections of mismatched primitives, e.g. number & bool is replaced by never, and
  • removing unions of functions, e.g. ((number?) -> number) | ((string?) -> string) is replaced by (nil) -> (number | string).

For example, normalizing (number?) & (string?) removes number & string, so all that is left is nil.

Our first attempt at implementing type normalization applied it liberally, but this resulted in dreadful performance (complex code went from typechecking in less than a minute to running overnight). The reason for this is annoyingly simple: there is an optimization in Luau’s subtyping algorithm to handle reflexivity (T is a subtype of T) that performs a cheap pointer equality check. Type normalization can convert pointer-identical types into semantically-equivalent (but not pointer-identical) types, which significantly degrades performance.

Because of these performance issues, we still use syntactic subtyping as our first check for subtyping, and only perform type normalization if the syntactic algorithm fails. This is sound, because syntactic subtyping is a conservative approximation to semantic subtyping.

Pragmatic semantic subtyping

Off-the-shelf semantic subtyping is slightly different from what is implemented in Luau, because it requires models to be set-theoretic, which requires that inhabitants of function types “act like functions.” There are two reasons why we drop this requirement.

Firstly, we normalize function types to an intersection of functions, for example a horrible mess of unions and intersections of functions:

((number?) -> number?) | (((number) -> number) & ((string?) -> string?))

normalizes to an overloaded function:

((number) -> number?) & ((nil) -> (number | string)?)

Set-theoretic semantic subtyping does not support this normalization, and instead normalizes functions to disjunctive normal form (unions of intersections of functions). We do not do this for ergonomic reasons: overloaded functions are idiomatic in Luau, but DNF is not, and we do not want to present users with such non-idiomatic types.

Our normalization relies on rewriting away unions of function types:

((A) -> B) | ((C) -> D)   →   (A & C) -> (B | D)

This normalization is sound in our model, but not in set-theoretic models.

Secondly, in Luau, the type of a function application f(x) is B if f has type (A) -> B and x has type A. Unexpectedly, this is not always true in set-theoretic models, due to uninhabited types. In set-theoretic models, if x has type never then f(x) has type never. We do not want to burden users with the idea that function application has a special corner case, especially since that corner case can only arise in dead code.

In set-theoretic models, (never) -> A is a subtype of (never) -> B, no matter what A and B are. This is not true in Luau.

For these two reasons (which are largely about ergonomics rather than anything technical) we drop the set-theoretic requirement, and use pragmatic semantic subtyping.

Negation types

The other difference between Luau’s type system and off-the-shelf semantic subtyping is that Luau does not support all negated types.

The common case for wanting negated types is in typechecking conditionals:

-- initially x has type T
if (type(x) == "string") then
  --  in this branch x has type T & string
else
  -- in this branch x has type T & ~string
end

This uses a negated type ~string inhabited by values that are not strings.

In Luau, we only allow this kind of typing refinement on test types like stringfunctionPart and so on, and not on structural types like (A) -> B, which avoids the common case of general negated types.

Prototyping and verification

During the design of Luau’s semantic subtyping algorithm, there were changes made (for example initially we thought we were going to be able to use set-theoretic subtyping). During this time of rapid change, it was important to be able to iterate quickly, so we initially implemented a prototype rather than jumping straight to a production implementation.

Validating the prototype was important, since subtyping algorithms can have unexpected corner cases. For this reason, we adopted Agda as the prototyping language. As well as supporting unit testing, Agda supports mechanized verification, so we are confident in the design.

The prototype does not implement all of Luau, just the functional subset, but this was enough to discover subtle feature interactions that would probably have surfaced as difficult-to-fix bugs in production.

Prototyping is not perfect, for example the main issues that we hit in production were about performance and the C++ standard library, which are never going to be caught by a prototype. But the production implementation was otherwise fairly straightforward (or at least as straightforward as a 3kLOC change can be).

Next steps

Semantic subtyping has removed one source of false positives, but we still have others to track down:

  • Overloaded function applications and operators
  • Property access on expressions of complex type
  • Read-only properties of tables
  • Variables that change type over time (aka typestates)

The quest to remove spurious red squiggles continues!

Acknowledgments

Thanks to Giuseppe Castagna and Ben Greenman for helpful comments on drafts of this post.


Alan coordinates the design and implementation of the Luau type system, which helps drive many of the features of development in Roblox Studio. Dr. Jeffrey has over 30 years of experience with research in programming languages, has been an active member of numerous open-source software projects, and holds a DPhil from the University of Oxford, England.



Source link



We liked the supernatural immersive sim Weird West (opens in new tab) quite a bit when it arrived earlier this year, and now it’s even better thanks to the addition of mod support in the latest patch. A handful of mods are already available for the game, including one that changes it from an isometric perspective to first person.

The “quirky” first-person mod isn’t officially supported by developer WolfEye Studios, but it was created by a Weird West developer: Joe Wintergreen, a systems designer on the game. Wintergreen said in a YouTube video that the project began with a quick first-person perspective mod that was “surprisingly cool but not particularly good,” and then got underway in earnest a few months later when WolfEye asked if he’d come back for a week or two to polish it up for release as one of Weird West’s first mods.



Source link

Something is rotten in the state of Revachol. This year has seen the gradual unfurling of a bitterly ironic real-world tale, one in which the creators of perhaps the best PC game ever (opens in new tab) appear to have been systemically cut-out of the company (opens in new tab) they co-founded, Disco Elysium studio ZA/UM: and are now fighting in the courts for some restorative justice.

How on Earth did it get to this point? One of the answers is relatively simple. Four concept sketches of a man in a scarf, the first glimpses of a Disco Elysium sequel, which were allegedly bought last year for just over €1 by a shell company controlled by a ZA/UM executive, and then immediately re-sold to ZA/UM for €4.8 million.



Source link


Readers of PCG’s weekend question (opens in new tab) will be well-aware of my GPU struggles, but for the unfamiliar, let’s just say that, well, circumstances have conspired such that I occasionally have to turn my PC upside down to make the graphics card work. Look, don’t worry, it’s fine, but I’m in the market for a new GPU, and some of these AMD deals have me seriously tempted to switch over from the green team.



Source link